题意:n个数,你可以给一个区间加上c,或者询问一个区间的和。
思路:线段树(成段更新)。简直模版得不能再模板。。不过我还是因为不熟练写了好些bug。
#include <iostream> #include <stdio.h> #include <cmath> #include <algorithm> #include <iomanip> #include <cstdlib> #include <string> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <ctype.h> #define ll long long using namespace std; struct node{ int l,r; ll val; ll add; }; node tree[400010]; ll num[100010]; ll build_tree(int n,int l,int r){ tree[n].l=l; tree[n].r=r; tree[n].add=0; if(l==r){ tree[n].val=num[l]; return num[l]; } int mid=(l+r)/2; tree[n].val=build_tree(n*2,l,mid)+build_tree(n*2+1,mid+1,r); return tree[n].val; } void update(int n,int l,int r,ll v){ tree[n].val+=(r-l+1)*v; if(tree[n].l==l&&tree[n].r==r){ if(l!=r)tree[n].add+=v; return; } int mid=(tree[n].l+tree[n].r)/2; if(tree[n].add){ update(n*2,tree[n].l,mid,tree[n].add); update(n*2+1,mid+1,tree[n].r,tree[n].add); tree[n].add=0; } if(r<=mid){ update(n*2,l,r,v); }else{ if(l<=mid){ update(n*2,l,mid,v); update(n*2+1,mid+1,r,v); }else{ update(n*2+1,l,r,v); } } } ll query(int n,int l,int r){ if(tree[n].l==l&&tree[n].r==r){ return tree[n].val; } int mid=(tree[n].l+tree[n].r)/2; if(tree[n].add){ update(n*2,tree[n].l,mid,tree[n].add); update(n*2+1,mid+1,tree[n].r,tree[n].add); tree[n].add=0; } // if(r<=mid){ return query(n*2,l,r); }else{ if(l<=mid){ return query(n*2,l,mid)+query(n*2+1,mid+1,r); }else{ return query(n*2+1,l,r); } } } int main(){ int n,q; while(cin>>n>>q){ for(int i=1;i<=n;i++){ scanf("%lld",&num[i]); } build_tree(1,1,n); while(q--){ char str[10]; scanf("%s",str); if(str[0]=='C'){ int a,b,c; scanf("%d%d%d",&a,&b,&c); update(1,a,b,c); }else{ int a,b; scanf("%d%d",&a,&b); ll ans=query(1,a,b); printf("%lld\n",ans); } } } return 0; }