POJ 3468-线段数区间更新

来源:互联网 发布:表单制作软件 编辑:程序博客网 时间:2024/05/18 13:48

POJ 3468

You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+1, … , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.
题目大意:给你一堆数,在区间里进行各种操作,询问区间的和、注意sum、和seg的数据类型是long long
真的是艰难,经历了3个小时终于A掉了,不过还是值得的。这样一来对线段树的区间更新认识更加深刻了,回来再把区间更新的原理写出来吧,虽然不是很困,但是时间真的有点晚了,我还有点饿
区间更新、区间求和更新延迟标记时注意

标记的叠加、叠加、叠加…省略无数次叠加

Pushdown

void Pushdown(int l,int r,int i){//操作结果延迟标记下压子区间 //同时更新子区间区间的sum    if(tree[i].seg==0)        return ;    int m=(l+r)>>1;    tree[i<<1].seg+=tree[i].seg;//注意这里是叠加    tree[i<<1].sum+=tree[i].seg*(m-l+1);    tree[i<<1|1].seg+=tree[i].seg;    tree[i<<1|1].sum+=tree[i].seg*(r-m);    tree[i].seg=0;//清楚延迟标记}

Update

void Update(int L,int R,int l,int r,int i,long long e){ //操作结果将目标区间打上延迟标记,更新路径上的sum       if(L<=l&&R>=r)       {           tree[i].seg+=e;//这里是细节           tree[i].sum+=(long long)(e*(r-l+1));           return;       }       Pushdown(l,r,i);       int m=(l+r)>>1;       if(L<=m)        Update(L,R,lson,e);       if(R>m)        Update(L,R,rson,e);       Pushup(i);}
#include<iostream>#include<cstdio>#include<cstring>#define lson l,m,i<<1#define rson m+1,r,i<<1|1using namespace std;const int maxn=100005;struct node{    int left,right;    long long sum;    long long seg;}tree[maxn<<2];void Pushup(int i){    tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;}void Pushdown(int l,int r,int i){//操作结果延迟标记下压子区间 //同时更新子区间区间的sum    if(tree[i].seg==0)        return ;    int m=(l+r)>>1;    tree[i<<1].seg+=tree[i].seg;//注意这里是叠加    tree[i<<1].sum+=tree[i].seg*(m-l+1);    tree[i<<1|1].seg+=tree[i].seg;    tree[i<<1|1].sum+=tree[i].seg*(r-m);    tree[i].seg=0;//清楚延迟标记}void Build(int l,int r,int i){    tree[i].left=l;    tree[i].right=r;    if(l==r)    {        scanf("%lld",&tree[i].sum);        return ;    }    int m=(l+r)>>1;    Build(lson);    Build(rson);    Pushup(i);}void Update(int L,int R,int l,int r,int i,long long e){ //操作结果将目标区间打上延迟标记,更新路径上的sum       if(L<=l&&R>=r)       {           tree[i].seg+=e;//这里是细节           tree[i].sum+=(long long)(e*(r-l+1));           return;       }       Pushdown(l,r,i);       int m=(l+r)>>1;       if(L<=m)        Update(L,R,lson,e);       if(R>m)        Update(L,R,rson,e);       Pushup(i);}long long Query(int L,int R,int l,int r,int i){//操作结果 求区间和、跟新途中延迟标记    if(L<=l&&R>=r)    {        return tree[i].sum;    }    long long ans=0;    Pushdown(l,r,i);    int m=(l+r)>>1;    if(L<=m)        ans+=Query(L,R,lson);    if(R>m)        ans+=Query(L,R,rson);    return ans;} int main() {     memset(tree,0,sizeof(tree));     int N,Q;     cin>>N>>Q;     Build(1,N,1);     for(int j=1;j<=Q;j++)     {         int a,b,c;         char str;         cin>>str;         if(str=='Q')         {             cin>>a>>b;          cout<<Query(a,b,1,N,1)<<endl;         }         if(str=='C')         {             cin>>a>>b>>c;             Update(a,b,1,N,1,c);         }     }     return 0; }
原创粉丝点击