zoukankan      html  css  js  c++  java
  • Poj3468-A Simple Problem with Integers(伸展树练练手)

    Description

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000. Each of the next Q lines represents an operation. "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000. "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15

    题意: 给出N个数,有两种操作
    Q a b 查询[a,b]区间的和
    C a b c [a,b]区间所有值加上c

    解析:成段更新问题,线段树已经可以做,我试着用伸展树做做。

    代码:
    //这题用线段树就可以做了,拿来用伸展树练练手
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn=100005;
    int A[maxn],cnt;  //A数组保存数,cnt是节点标号,我是用数组模拟的
    struct treap
    {
        treap* son[2];  //左右儿子
        int s;
        LL v,add,sum;
        treap(){  s=v=add=sum=0; son[0]=son[1]=NULL; }
        treap(LL nv);
        int rk(){ return son[0]->s+1; }  //排名,第几个数
        int cmp(int k)  //比较,如果相等返回-1,小于返回0,大于1
        {
            if(k==rk()) return -1;
            return k<rk()?0:1;
        }
        void Set(LL d)
        {
            v+=d;
            add+=d;
            sum+=d*s;
        }
        void pushup()
        {
            s=son[0]->s+son[1]->s+1;
            sum=son[0]->sum+son[1]->sum+v;
        }
        void pushdown()  //处理懒惰标记
        {
            if(add!=0)
            {
                son[0]->Set(add);
                son[1]->Set(add);
                add=0;
            }
        }
    }null,tr[maxn];
    treap::treap(LL nv)
    {
        sum=v=nv;
        s=1;
        add=0;
        son[0]=son[1]=&null;
    }
    treap* NewNode(LL x)
    {
        tr[cnt]=treap(x);
        return tr+cnt++;
    }
    struct splaytree
    {
        int Size;
        treap* root;
        splaytree(){ Size=0; root=&null; }
        void Rotate(treap* &t,int d)  //翻转操作
        {
            t->pushdown();
            treap* p=t->son[d^1];
            p->pushdown();
            t->son[d^1]=p->son[d];
            p->son[d]=t;
            t->pushup();
            t=p;
            t->pushup();
        }
        void Splay(treap* &t,int k)  //将第k大的节点伸展到根
        {
            t->pushdown();
            int d=t->cmp(k);
            if(d!=-1)
            {
                if(d) Splay(t->son[d],k- t->rk());
                else Splay(t->son[d],k);
                Rotate(t,d^1);
            }
        }
        void Build(treap* &t,int le,int ri)  //将N个数建成一棵树
        {
            if(le>ri) return;
            int mid=(le+ri)/2;
            t=NewNode(A[mid]);
            Build(t->son[0],le,mid-1);
            Build(t->son[1],mid+1,ri);
            t->pushup();
        }
        LL Query(treap* &t,int x,int y)
        {
            LL ret=0;
            Splay(t,y);
            ret+=t->son[0]->sum+t->v;
            if(x>1)
            {
                Splay(t,x-1);
                ret-=t->son[0]->sum+t->v;
            }
            return ret;
        }
        void Add(treap* &t,int x,int y,int add)
        {
            Splay(t,y);
            t->v+=add; t->sum+=add*y;
            t->son[0]->Set(add);
            if(x>1)
            {
                Splay(t,x-1);
                t->v-=add; t->sum-=add*(x-1);
                t->son[0]->Set(-add);
            }
        }
    };
    int main()
    {
        int N,Q;
        while(scanf("%d%d",&N,&Q)!=EOF)
        {
            for(int i=1;i<=N;i++) scanf("%d",&A[i]);
            splaytree spt;
            cnt=0;
            spt.Build(spt.root,1,N);
            int x,y,d;
            char op[3];
            while(Q--)
            {
                scanf("%s",op);
                if(op[0]=='Q')
                {
                    scanf("%d%d",&x,&y);
                    printf("%lld
    ",spt.Query(spt.root,x,y));
                }
                else
                {
                    scanf("%d%d%d",&x,&y,&d);
                    spt.Add(spt.root,x,y,d);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    [转载]oracle中的exists 和not exists 用法详解
    oracle中sql语句的优化(转帖)
    BizTalk Server 2010 使用 WCF Service [ 上篇 ]
    冒泡排序
    一起复习几何(4)
    手把手教你升级到 Mysql 5.5
    BizTalk Server 2010 映射器(Mapper) [ 上篇 ]
    基于OpenGL的渲染引擎
    BizTalk Server 2010 映射器(Mapper) [ 下篇 ]
    BizTalk Server 2010 映射器(Mapper) [ 中篇 ]
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5733042.html
Copyright © 2011-2022 走看看