區間更新區間求和板子 *(線段樹lazy)
阿新 • • 發佈:2019-02-08
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
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.
題意:Q查詢區間和,C區間a到b全加上c。
lazy模板
#include<stdio.h> using namespace std; #define ll long long #define N 100010 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct nomd { int l,r; int mid(){ return (l+r)>>1; } }tree[N<<2]; ll add[N<<2],sum[N<<2]; void up(int rt)//跟新父親值 建樹時用一次 跟新時用一次 { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void down(int rt,int m)//lazy標記 m 是tree(r-l)+1.區間數的個數 跟新查詢各用一次 { if(add[rt])//lazy標記是他沒有將下面兒子全部標記,而是查詢到了在往下繼續標記減少時間 { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; sum[rt<<1]+=add[rt]*(m-(m>>1)); sum[rt<<1|1]+=add[rt]*(m>>1); add[rt]=0; } } void build(int l,int r,int rt)//建樹 { tree[rt].l=l;tree[rt].r=r; add[rt]=0; if(l==r)//在這裡輸入確實挺漲姿勢的.... { scanf("%lld",&sum[rt]); return ; } int m=tree[rt].mid(); build(lson);//巨集定義了 二分思想 build(rson); up(rt); } void update(int c,int l,int r,int rt) { if(tree[rt].l==l&&tree[rt].r==r)//跟新和查詢過程差不多 正好包含 { add[rt]+=c; sum[rt]+=(ll)c*(r-l+1); return; } if(tree[rt].l==tree[rt].r) return;//走到最後了 down(rt,tree[rt].r-tree[rt].l+1);//更新一下add值 int m=tree[rt].mid(); if(r<=m) update(c,l,r,rt<<1);//全在左邊 else if(l>m) update(c,l,r,rt<<1|1);//全在右邊 else//兩邊都有 { update(c,l,m,rt<<1); update(c,m+1,r,rt<<1|1); } up(rt); } ll query(int l,int r,int rt) { if(tree[rt].l==l&&tree[rt].r==r)// { return sum[rt]; } down(rt,tree[rt].r-tree[rt].l+1);//查詢到了就要讀取add裡的值 int m=tree[rt].mid(); ll res=0; if(r<=m) res+=query(l,r,rt<<1);// else if(l>m) res+=query(l,r,rt<<1|1);// else// { res+=query(l,m,rt<<1)+query(m+1,r,rt<<1|1); } return res; } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { build(1,n,1); for(int i=0;i<m;i++) { char w[10]; scanf("%s",w); if(w[0]=='Q') { int e,ee; scanf("%d %d",&e,&ee); printf("%lld\n",query(e,ee,1)); } else { int e,ee,eee; scanf("%d %d %d",&e,&ee,&eee); update(eee,e,ee,1); } } } return 0; }