(本人本题完成于2016-7-23)
(已于2016-8-29更新伸展树做法)
题目大意:有一个数列A有N个数,对这个数列有两种操作:1.C a b c:将Aa,Aa+1,...,Ab都加上c。2.Q a b:询问Aa,Aa+1,...,Ab的和。根据询问给出答案。
做法:一道非常裸的线段树题,没什么可说的,由于数字较大需用long long。
(2016.8.29更新:此题也为伸展树区间处理的入门题,但感觉似乎有些小题大做...不过当做模板参照一下也是好的,所以也将代码陈列在这里。)
以下是本人代码:
线段树:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int n,q,a,b;
long long A[100010]={0},c;
char o;
struct node
{
int l,r;
long long sum,p;
}seg[300010];
void buildtree(int no,int l,int r)
{
int mid=(l+r)/2;
seg[no].l=l;seg[no].r=r;seg[no].p=0;
if (l==r) seg[no].sum=A[l];
else
{
buildtree(2*no,l,mid);
buildtree(2*no+1,mid+1,r);
seg[no].sum=seg[2*no].sum+seg[2*no+1].sum;
}
}
void add(int no,int s,int t,long long c)
{
int mid=(seg[no].l+seg[no].r)/2;
if (seg[no].l>=s&&seg[no].r<=t)
{
seg[no].p+=c;
seg[no].sum+=(long long)(seg[no].r-seg[no].l+1)*c;
return;
}
seg[2*no].p+=seg[no].p;seg[2*no+1].p+=seg[no].p;
seg[2*no].sum+=(long long)(seg[2*no].r-seg[2*no].l+1)*seg[no].p;
seg[2*no+1].sum+=(long long)(seg[2*no+1].r-seg[2*no+1].l+1)*seg[no].p;
seg[no].p=0;
if (s<=mid) add(2*no,s,t,c);
if (t>mid) add(2*no+1,s,t,c);
seg[no].sum=seg[2*no].sum+seg[2*no+1].sum;
}
long long query(int no,int s,int t)
{
int mid=(seg[no].l+seg[no].r)/2;
if (seg[no].l>=s&&seg[no].r<=t) return seg[no].sum;
seg[2*no].p+=seg[no].p;seg[2*no+1].p+=seg[no].p;
seg[2*no].sum+=(long long)(seg[2*no].r-seg[2*no].l+1)*seg[no].p;
seg[2*no+1].sum+=(long long)(seg[2*no+1].r-seg[2*no+1].l+1)*seg[no].p;
seg[no].p=0;
long long tot=0;
if (s<=mid) tot+=query(2*no,s,t);
if (t>mid) tot+=query(2*no+1,s,t);
return tot;
}
int main()
{
scanf("%d %d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%lld",&A[i]);
scanf("
");
buildtree(1,1,n);
for(int i=1;i<=q;i++)
{
scanf("%c",&o);
if (o=='C')
{
scanf("%d %d %lld
",&a,&b,&c);
add(1,a,b,c);
}
if (o=='Q')
{
scanf("%d %d
",&a,&b);
printf("%lld
",query(1,a,b));
}
}
return 0;
}
伸展树(2016.8.29更新):
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
long long n,q,num[100010],root=0,top=0;
long long val[100010],sum[100010],p[100010],siz[100010],ch[100010][2],pre[100010];
char op[20];
void newnode(long long &x,long long c,long long f)
{
x=++top;
ch[x][0]=ch[x][1]=0;siz[x]=1;
val[x]=sum[x]=c;p[x]=0;
pre[x]=f;
}
void pushdown(long long x)
{
if (!p[x]) return;
int l=ch[x][0],r=ch[x][1];
p[l]+=p[x];p[r]+=p[x];
val[l]+=p[x];val[r]+=p[x];
sum[l]+=siz[l]*p[x];
sum[r]+=siz[r]*p[x];
p[x]=0;
}
void pushup(long long x)
{
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
}
void rotate(long long x,bool f)
{
long long y=pre[x];
pushdown(y);pushdown(x);
ch[y][!f]=ch[x][f];
pre[ch[x][f]]=y;
ch[x][f]=y;
if (pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];pre[y]=x;
pushup(y);
}
void Splay(long long x,int goal)
{
pushdown(x);
while (pre[x]!=goal)
{
pushdown(pre[pre[x]]);pushdown(pre[x]);pushdown(x);
if (pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
else
{
bool f=(ch[pre[pre[x]]][0]==pre[x]);
if (ch[pre[x]][f]==x) rotate(x,!f),rotate(x,f);
else rotate(pre[x],f),rotate(x,f);
}
}
pushup(x);
if (goal==0) root=x;
}
void rotateto(long long k,long long goal)
{
long long i=root;
pushdown(i);
while(siz[ch[i][0]]+1!=k)
{
if (siz[ch[i][0]]+1<k) k-=siz[ch[i][0]]+1,i=ch[i][1];
else i=ch[i][0];
pushdown(i);
}
Splay(i,goal);
}
void buildtree(long long &x,long long l,long long r,long long f)
{
if (l>r) return;
long long mid=(l+r)>>1;
newnode(x,num[mid],f);
buildtree(ch[x][0],l,mid-1,x);
buildtree(ch[x][1],mid+1,r,x);
pushup(x);
}
void input()
{
ch[0][0]=ch[0][1]=siz[0]=sum[0]=p[0]=pre[0]=val[0]=0;
newnode(root,-1,0);
newnode(ch[root][1],-1,root);
siz[root]=2;
for(int i=1;i<=n;i++) scanf("%lld",&num[i]);
buildtree(ch[ch[root][1]][0],1,n,ch[root][1]);
pushup(ch[root][1]);pushup(root);
}
void change(long long s,long long t,long long v)
{
rotateto(s,0);
rotateto(t+2,root);
long long g=ch[ch[root][1]][0];
val[g]+=v;
p[g]+=v;
sum[g]+=siz[g]*v;
}
long long query(long long s,long long t)
{
rotateto(s,0);
rotateto(t+2,root);
long long g=ch[ch[root][1]][0];
return sum[g];
}
int main()
{
scanf("%lld%lld",&n,&q);
input();
for(int i=1;i<=q;i++)
{
long long s,t,v;
scanf("%s",op);
if (op[0]=='C')
{
scanf("%lld%lld%lld",&s,&t,&v);
change(s,t,v);
}
if (op[0]=='Q')
{
scanf("%lld%lld",&s,&t);
printf("%lld
",query(s,t));
}
}
return 0;
}