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
题解:
用add标志标记已经修改但子节点未被修改的节点,在查询时更新需要向下更新的子节点即可
代码:
//#include<bits/stdc++.h> #include<algorithm> #include <iostream> #include <fstream> #include <cstdlib> #include <cstring> #include <cassert> #include <cstdio> #include <vector> #include <string> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define P(a,b,c) make_pair(a,make_pair(b,c)) #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,a,n) for (int i=n;i>=a;i--) #define CLR(vis) memset(vis,0,sizeof(vis)) #define MST(vis,pos) memset(vis,pos,sizeof(vis)) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef pair<int,pair<int,int> >pii; typedef long long ll; typedef unsigned long long ull; const ll mod = 1000000007; const int INF = 0x3f3f3f3f; ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; } template<class T>inline void gmax(T &A, T B) { (A<B)&&(A=B);//if(B>A)A=B; } template<class T>inline void gmin(T &A, T B) { (A>B)&&(A=B);//if(B<A)A=B; } template <class T> inline bool scan_d(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; //EOF while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } inline void outt(int x) { if(x>9) outt(x/10); putchar(x%10+'0'); } const int maxn = 1e6+10; struct SegmentTree{ int l,r; long long sum, add; #define l(x) tree[x].l #define r(x) tree[x].r #define sum(x) tree[x].sum #define add(x) tree[x].add }tree[1000010*4]; int a[1000010],n,m; void build(int p,int l,int r){ l(p)=l,r(p)=r; if(l==r){ sum(p)=a[l];return ; } int mid=(l+r)/2;//只有这里的一半是直接用传入的l,r,但实际上这里的l,r就是下面的p.l,p.r build(p*2,l,mid); build(p*2+1,mid+1,r); sum(p)=sum(p*2)+sum(p*2+1); } //延迟标记代表:该节点已经被修改,但子节点尚未被更新 void spread(int p){ if(add(p)){ sum(p*2) += add(p)*(r(p*2)-l(p*2)+1); //更新左子节点信息 sum(p*2+1) += add(p)*(r(p*2+1)-l(p*2+1)+1);//更新右子节点信息 add(p*2) += add(p); //给左子节点打延迟标记 add(p*2+1) += add(p); add(p) = 0;//清楚p节点的标记 } } void change(int p,int l,int r,int d){ if(l<=l(p) && r>=r(p)){//完成覆盖 sum(p)+=(long long)d*(r(p)-l(p)+1);//更新节点信息 add(p)+=d;//给节点打延迟标记 return ; } spread(p); //下传延迟标记 int mid=(l(p)+r(p))/2; //这里的中间是当前节点的中间(或者说是偏左的中间)位置 if(l<=mid)change(p*2,l,r,d); if(r>mid)change(p*2+1,l,r,d);//注意这里不是非此即彼的关系 sum(p)=sum(p*2)+sum(p*2+1); } long long ask(int p,int l,int r){ if(l<=l(p) && r>=r(p))return sum(p); spread(p); int mid=(l(p)+r(p))/2; long long val=0; if(l <= mid) val+=ask(p*2,l,r);//注意!这里对中间元素进行比较的是l不是tree[p].l if(r > mid) val+=ask(p*2+1,l,r); return val; } char cmd[10]; int main(){ int n,m; scan_d(n),scan_d(m); rep(i,1,n)scan_d(a[i]); build(1,1,n); while(m--){ scanf("%s", cmd); int l,r,d; scan_d(l); scan_d(r); if(cmd[0]=='Q'){ printf("%I64d\n", ask(1,l,r)); }else{ scan_d(d); change(1,l,r,d); } } return 0; }