【POJ3468】A Simple Problem with Integers-线段树和伸展树入门题

来源:互联网 发布:软件著作权个人申请 编辑:程序博客网 时间:2024/06/06 12:58

(本人本题完成于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("\n");    buildtree(1,1,n);  for(int i=1;i<=q;i++)  {    scanf("%c",&o);if (o=='C'){  scanf("%d %d %lld\n",&a,&b,&c);  add(1,a,b,c);}if (o=='Q'){  scanf("%d %d\n",&a,&b);  printf("%lld\n",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\n",query(s,t));}  }    return 0;}


0 0
原创粉丝点击