您的位置:首页 > 其它

codevs 1082 一维树状数组区间修改区间查询

2017-12-06 23:35 302 查看
吃什么

Sol

容斥+画图理解

数组ca存的是修改区间覆盖当前点时应该加的值

数组cb存的是修改区间完全在当前点前面时对当前点的前缀和影响

当然还有其它情况

有时间的话会补图

另外一种方法

利用差分数组

写法可能更简洁

数学推导的思路比直接脑补容斥原理更简单一些

比如扩展到二维的 bzoj 3132

Code

// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;

const int N=200010;
int n,m;
LL a
;
LL ca
,cb
;

int lowbit(int x){return x&(-x);}

void adda(int p,LL v){
for(int i=p;i<=n;i+=lowbit(i))
ca[i]+=v;
}

void addb(int p,LL v){
for(int i=p;i<=n;i+=lowbit(i))
cb[i]+=v;
}

LL sum(int x,int y){
LL ret=0;
for(int i=x-1;i;i-=lowbit(i)) ret+=cb[i]-1ll*(x-1)*ca[i];
for(int i=y;i;i-=lowbit(i)) ret+=1ll*y*ca[i]-cb[i];
return ret;
}

int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
adda(i,a[i]);
adda(i+1,-a[i]);
addb(i,(i-1)*a[i]);
addb(i+1,-i*a[i]);
}
int op,x,y;
LL z;
scanf("%d",&m);
while(m--){
scanf("%d%d%d",&op,&x,&y);
if(op==1){
scanf("%lld",&z);
adda(x,z);
adda(y+1,-z);
addb(x,1ll*(x-1)*z);
addb(y+1,-1ll*y*z);
}
if(op==2){
printf("%lld\n",sum(x,y));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐