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

(本人本题完成于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;
}


posted @ 2016-07-23 18:09  Maxwei_wzj  阅读(112)  评论(0编辑  收藏  举报