[tem]树状数组

通过差分可以玩区间:

bi=ai-a(i-1)

查询时考虑位置对答案的贡献 推导一下

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N=1e5;
 8 
 9 ll n,a[N],b[N],c1[N],c2[N];
10 
11 //basic
12 inline int lowbit(int x){return x&-x;}
13 ll sum(ll *c,int x){
14     ll ret=0;
15     for(;x>0;x-=lowbit(x)) ret+=c[x];
16     return ret;
17 }
18 ll query(ll *c,int l,int r){
19     return sum(c,r)-sum(c,l-1);
20 }
21 void addPoint(ll *c,int x,ll v){
22     for(;x<=n;x+=lowbit(x)) c[x]+=v;
23 }
24 void build(ll *c,ll *a,ll n){
25     for(int i=1;i<=n;i++){
26         c[i]+=a[i];
27         if(i+lowbit(i)<=n)
28             c[i+lowbit(i)]+=c[i];   //!!c[i] or while
29     }
30 }
31 
32 //interval-interval
33 void initB(ll *b,ll *a){
34     b[1]=a[1];
35     for(int i=2;i<=n;i++) b[i]=a[i]-a[i-1];
36 }
37 void addRange(int l,int r,ll v){
38     addPoint(c1,l,v);        addPoint(c2,l,v*l);
39     addPoint(c1,r+1,-v);    addPoint(c2,r+1,-v*(r+1));
40 }
41 ll sumRange(int l,int r){
42     return query(c1,1,l)*(r-l+1)+ query(c1,l+1,r)*(r+1) -query(c2,l+1,r);
43 }
44 
45 int t,l,r;
46 ll v;
47 int main(){
48     
49     //freopen("in.txt","r",stdin);
50     //freopen("1.txt","w",stdout);
51     
52     cin>>n>>t;
53     for(int i=1;i<=n;i++) cin>>a[i];
54 //    for(int i=1;i<=n;i++){
55 //        addRange(i,i,a[i]);
56 //    }
57 
58     initB(b,a);
59     build(c1,b,n);
60     for(int i=1;i<=n;i++) b[i]*=i;
61     build(c2,b,n);
62     
63     while(t--){
64         int flag;
65         cin>>flag;
66         if(flag==1){
67             cin>>l>>r;
68             cout<<sumRange(l,r)<<"\n";
69         }else{
70             cin>>l>>r>>v;
71             addRange(l,r,v);
72             cout<<sumRange(l,r)<<"\n";
73         }
74     }
75 }

 

posted @ 2016-08-06 23:53  Candy?  阅读(433)  评论(0编辑  收藏  举报