分析(树状数组)
首先先讲树状数组的做法,别问我为什么!
同3368一样用差分数组。
使
差
分
数
组
1
到
x
的
和
为
a
n
s
(
x
)
使差分数组1到x的和为ans(x)
使差分数组1到x的和为ans(x)。
建立一个新的树状数组
a
n
s
1
(
x
)
=
a
n
s
(
x
)
−
a
n
s
(
x
−
1
)
ans1(x)=ans(x)-ans(x-1)
ans1(x)=ans(x)−ans(x−1)
不过那也就是x——y的答案为
(
y
∗
a
n
s
(
y
)
−
(
x
−
1
)
∗
a
n
s
1
(
x
−
1
)
)
−
(
a
n
s
(
y
)
−
a
n
s
1
(
x
−
1
)
)
(y*ans(y)-(x-1)*ans1(x-1))-(ans(y)-ans1(x-1))
(y∗ans(y)−(x−1)∗ans1(x−1))−(ans(y)−ans1(x−1))
树状数组代码
#include <cstdio>
#include <cctype>
#define ll long long
using namespace std;
ll n,a[500001],b[500001],m;
ll lowbit(ll x){return x&(-x);}
ll in(){
ll ans=0; char c=getchar(); int f=1;
while (!isdigit(c)&&c!='-') c=getchar();
if (c=='-'){f=-f;c=getchar();}
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void add(ll x,ll k){
while (x<=n){
a[x]+=k;
x+=lowbit(x);
}
}
void add1(ll x,ll k){
while (x<=n){
b[x]+=k;
x+=lowbit(x);
}
}
ll sum1(ll x){
ll ans=0;
while (x>0){
ans+=b[x];
x-=lowbit(x);
}
return ans;
}
ll sum(ll x){
ll ans=0;
while (x>0){
ans+=a[x];
x-=lowbit(x);
}
return ans;
}
int main(){
n=in(); m=in();
for (ll i=1,o=0,x;i<=n;i++) x=in(),add(i,x-o),add1(i,(i-1)*(x-o)),o=x;
while (m--){
ll q,l,r,x; q=in();
if (q==1){l=in(); r=in(); x=in(); add(r+1,-x); add(l,x); add1(l,x*(l-1)); add1(r+1,-x*r);}
else {l=in(); r=in(); printf("%lld\n",r*sum(r)-sum1(r)-(l-1)*sum(l-1)+sum1(l-1));}//查找
}
return 0;
}
分析(线段树)
建造
inline ll build(ll l,ll r,ll k){
if (l==r) return tree[k].w=a[r];
else return tree[k].w=build(l,(l+r)>>1,k<<1)+build(((l+r)>>1)+1,r,(k<<1)+1);
}
添改
void update(ll l,ll r,ll x,ll y,ll res,ll k){
if (x==l&&y==r) {tree[k].w+=res*(r-l+1); tree[k].lazy+=res; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);//左边的lazy标记
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);//右边的lazy标记
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) update(l,mid,x,y,res,k<<1);
else if (x>mid) update(mid+1,r,x,y,res,(k<<1)+1);
else update(l,mid,x,mid,res,k<<1),update(mid+1,r,mid+1,y,res,(k<<1)+1);
tree[k].w=tree[(k<<1)+1].w+tree[k<<1].w;
}
查找
void find(ll l,ll r,ll x,ll y,ll k){
if (x==l&&y==r) {ans+=tree[k].w; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) find(l,mid,x,y,k<<1);
else if (x>mid) find(mid+1,r,x,y,(k<<1)+1);
else find(l,mid,x,mid,k<<1),find(mid+1,r,mid+1,y,(k<<1)+1);
}
线段树代码
#include <cstdio>
#include <cctype>
#define ll long long
using namespace std;
struct node{
ll w,lazy;
}tree[2000001]; ll n,m,ans,a[500001];
inline ll inp(){
char c=getchar(); ll ans=0,f=1;
while (!isdigit(c)&&c!='-') c=getchar();
if (c=='-') f=-f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void find(ll l,ll r,ll x,ll y,ll k){
if (x==l&&y==r) {ans+=tree[k].w; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) find(l,mid,x,y,k<<1);
else if (x>mid) find(mid+1,r,x,y,(k<<1)+1);
else find(l,mid,x,mid,k<<1),find(mid+1,r,mid+1,y,(k<<1)+1);
}
inline ll build(ll l,ll r,ll k){
if (l==r) return tree[k].w=a[r];
else return tree[k].w=build(l,(l+r)>>1,k<<1)+build(((l+r)>>1)+1,r,(k<<1)+1);
}
void update(ll l,ll r,ll x,ll y,ll res,ll k){
if (x==l&&y==r) {tree[k].w+=res*(r-l+1); tree[k].lazy+=res; return;}
ll mid=(l+r)>>1;
if (tree[k].lazy){
tree[k<<1].w+=tree[k].lazy*(mid-l+1);
tree[k<<1].lazy+=tree[k].lazy;
tree[(k<<1)+1].w+=tree[k].lazy*(r-mid);
tree[(k<<1)+1].lazy+=tree[k].lazy;
tree[k].lazy=0;
}
if (y<=mid) update(l,mid,x,y,res,k<<1);
else if (x>mid) update(mid+1,r,x,y,res,(k<<1)+1);
else update(l,mid,x,mid,res,k<<1),update(mid+1,r,mid+1,y,res,(k<<1)+1);
tree[k].w=tree[(k<<1)+1].w+tree[k<<1].w;
}
inline void in1(ll &x,ll &y){x=inp(); y=inp();}
int main(){
n=inp(); m=inp();
for (ll i=1;i<=n;i++) a[i]=inp();
build(1,n,1);
while (m--){
ll q=inp(),x,y,k;ans=0;
if (q==1) in1(x,y),k=inp(),update(1,n,x,y,k,1);
else in1(x,y),find(1,n,x,y,1),printf("%lld\n",ans);
}
return 0;
}