A Simple Problem with Integers(線段樹區間更新)
阿新 • • 發佈:2018-12-10
【題意】 給定長度為 的序列 ,有 次操作,操作分兩種 表示將序列中 所有元素都加上一個數字 表示查詢序列 的元素之和
【思路】 線段樹區間更新,維護區間和並用lazy標記進行區間更新
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define node tree[id] #define lson tree[id<<1] #define rson tree[id<<1|1] using namespace std; typedef long long ll; const int maxn=100005; struct Tree{ int left,right; ll sum,lazy; }tree[maxn<<2]; int n,q; ll a[maxn]; void pushup(int id){node.sum=lson.sum+rson.sum;} void pushdown(int id){ if(node.lazy && node.left!=node.right){ lson.lazy+=node.lazy; lson.sum+=node.lazy*(ll)(lson.right-lson.left+1); rson.lazy+=node.lazy; rson.sum+=node.lazy*(ll)(rson.right-rson.left+1); node.lazy=0; } } void build(int id,int le,int ri){ node.left=le; node.right=ri; node.lazy=0; if(le==ri){ node.sum=a[le]; return; } int mid=(le+ri)>>1; build(id<<1,le,mid); build(id<<1|1,mid+1,ri); pushup(id); } ll query(int id,int le,int ri){ if(node.left==le && node.right==ri){ return node.sum; } pushdown(id); int mid=(node.left+node.right)>>1; if(ri<=mid) return query(id<<1,le,ri); else if(le>mid) return query(id<<1|1,le,ri); else return query(id<<1,le,mid)+query(id<<1|1,mid+1,ri); } void update(int id,int le,int ri,ll val){ if(node.left==le && node.right==ri){ node.sum+=val*(ll)(node.right-node.left+1); node.lazy+=val; return; } pushdown(id); int mid=(node.left+node.right)>>1; if(ri<=mid) update(id<<1,le,ri,val); else if(le>mid) update(id<<1|1,le,ri,val); else{ update(id<<1,le,mid,val); update(id<<1|1,mid+1,ri,val); } pushup(id); } int main(){ while(scanf("%d%d",&n,&q)==2){ for(int i=1;i<=n;++i) scanf("%lld",&a[i]); build(1,1,n); while(q--){ char op[2]; scanf("%s",op); if(op[0]=='Q'){ int a,b; scanf("%d%d",&a,&b); printf("%lld\n",query(1,a,b)); } else{ int a,b; ll c; scanf("%d%d%lld",&a,&b,&c); update(1,a,b,c); } } } return 0; }