pku--3468 A Simple Proble with Integers(線分樹)
3978 ワード
テーマ接続:http://poj.org/problem?id=3468
Time Limit:5000 MS Memory Limit:131772 K Total Submissions:17698 Acceptted:4581 Case Time Limit:20000 MS Description You have N integers、A 1、A 2、…You need to deal with twokids of operations.One type of operation isto add some given number to each number in a given interval.The otheher isto ask for the sum of numbersinininterval.InputThe firs firs inininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininof A 1,A 2,…AN.-100000≦Ai≦100000 000.Each of the next Qラインs represents an operation.「C a b c」means adding c to each of Aa,Aa+1,…,Ab.-10000≦c≦10000.「Q a b」meansquerythe sum of Aa,A+1,…Ab.Output You need to answer all Q command in order.One answer in a line.Sample Input 10 1 2 3 3 3 4 4 7 7 8 9 Q 4 1 10 Q 2 4 C 3 3 3 3 Q 2 4 Sample Output 4 55 Hige The mashe exted of langed 32 bit。
件名:
Q(1≦Q≦100,000)個数A 1、A 2…AQと、複数回行われるかもしれない二つの動作:1)ある区間Ai…Ajの個数にn(n可変)2を加えて、ある区間Ai…Ajの数の和を求める。
問題のデータ規模は簡単な方法で解決できません。
本人も一日目は線分樹に接触しました。前のACで水割りの線分樹を作ったら、基本的に自分で線分樹を作ることができます。
本題の解法は線分樹を利用したものです。
注意すべきなのは1.データ範囲で、データを保存するにはlong longまたは_u uint 64保存(区間を除いて整形が可能です。他の最後は64ビットを使用します。)
2.和えるだけで、加数するたびに葉っぱノードに更新します。速度が遅すぎるのは避けなければなりません。本題樹ノード構造:struct CNode{ int a,b;///区間起点と終点 CNode*left、*right; long long nSum;//元の和 long long Inc;//増分cの積算}本ノードの区間の和は、実はnSum+Inc*(R-L+1)です。
3.増加時に、プラスの区間がノードをちょうどカバーすると、そのノードのInc値を増加して、もう下に進まない。そうでないとnSumを更新して、さらにインクリメンタルをクエリに転送します。もし検査待ち区間がノードをちょうどカバーしていないなら、ノードのIncを下にバンドして、Incに代表されるすべての増分をnSumに加えてから、Incを0にクリアして、次に照会します。
#include <iostream>
using namespace std;
#define MAXN 100010
int N,Q;
__int64 num[MAXN], ans ,x;
struct data
{
__int64 sum,inc;
int l,r;
}Tree[4*MAXN];
void CreateTree(int k,int l,int r) //
{
Tree[k].l = l;
Tree[k].r = r;
Tree[k].inc = 0;
if(l == r)
Tree[k].sum = num[l];
else
{
int mid=(l+r)>>1;
CreateTree(k+k,l,mid);
CreateTree(k+k+1,mid+1,r);
Tree[k].sum = Tree[k+k].sum + Tree[k+k+1].sum;
}
}
void Add(int k,int l,int r,__int64 inc) //C
{
if(Tree[k].l == l && Tree[k].r == r)
{
Tree[k].inc += inc;
}
else
{
int mid = Tree[k+k].r;
Tree[k].sum += (r-l+1)*inc;
if(l>mid)
Add(k+k+1,l,r,inc);
else if(r<=mid)
Add(k+k,l,r,inc);
else
{
Add(k+k ,l,mid,inc);
Add(k+k+1 ,mid+1,r,inc);
}
}
}
void Query(int k,int l,int r,__int64 temp)
{
temp += Tree[k].inc;
if(Tree[k].l == l &&Tree[k].r == r)
{
ans+= Tree[k].sum + temp * (r-l+1);
}
else
{
int mid = Tree[k+k].r;
if(l>mid)
Query(k+k+1,l,r,temp);
else if(r<=mid)
Query(k+k,l,r,temp);
else
{
Query(k+k ,l,mid,temp);
Query(k+k+1 ,mid+1,r,temp);
}
}
}
int main()
{
int i,j;
char ch;
while(scanf("%d%d",&N,&Q)!=EOF)
{
for(i=1;i<=N;i++)
scanf("%I64d",&num[i]);
CreateTree(1,1,N);
while(Q--)
{
getchar();
scanf("%c %d %d",&ch,&i,&j);
if(ch=='Q')
{
ans = 0;
Query(1,i,j,0);
printf("%I64d
",ans);
}
else
{
scanf("%I64d",&x);
Add(1,i,j,x);
}
}
}
}