• 【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("
    ");
      
      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;
    }
    


  • 相关阅读:
    循环播放音乐
    在发板实现24位jpg和bmp图片用手划动显示上一张与下一张图片
    AnsiIO
    PosixIO
    java3
    java2
    java1
    ios音乐播放器demo
    添加文章查看连接
    elementary os变成mac风(笔记)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9794005.html
Copyright © 2020-2023  润新知