zoukankan      html  css  js  c++  java
  • hdu4453-Looploop(伸展树)

    题目有很多图,不好粘贴。。。。。

    题意:给出N个数和K1,K2的值,最开始指针指向第一个数,有6种操作

    add x : 给前K2个数都增加x

    reverse : 翻转前K1个数

    insert x : 在所指的数右边(顺时针)插入一个数

    delete x : 删除指针所指的这个数,并且指针向右移(顺时针)

    move x : x=1则指向向左移(逆时针),为2向右移(顺时针)

    query : 输出指针所指的数

    解析:这题涉及到插入删除,和给一段区间加值,线段树不能增加删除,链表的话又不能快速的给一段区间加数,所以只能用伸展树了。伸展树支持的操作很多,既有线段树的特性也有链表的特性。但是写起来复杂,所以一般题目如果能用常用的数据结构解决的就不要用伸展树了。我不具体介绍伸展树,自己下去多学学再看这题会容易许多。

    源代码

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int INF=1e9+7;
    const int maxn=200005;
    int A[maxn],cnt;  //A数组保存数,cnt是节点标号,我是用数组模拟的
    struct treap
    {
        treap* son[2];  //左右儿子
        int v,s,add,lazy;  //v是值,s是大小,add是懒惰标记增加的值,lazy是懒惰标记是否需要翻转
        treap(){ v=s=add=lazy=0; son[0]=son[1]=NULL; }
        treap(int 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 pushup(){ s=son[0]->s+son[1]->s+1; }  //更新大小
        void pushdown()  //处理懒惰标记
        {
            if(lazy)
            {
                swap(son[0],son[1]);
                son[0]->lazy^=1;
                son[1]->lazy^=1;
                lazy=0;
            }
            if(add)
            {
                v+=add;
                son[0]->add+=add;
                son[1]->add+=add;
                add=0;
            }
        }
    }null,tr[maxn];
    treap::treap(int nv)
    {
        v=nv;
        s=1;
        add=lazy=0;
        son[0]=son[1]=&null;
    }
    treap* NewNode(int 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();
        }
        void Add(treap* &t,int k,int a)  //加值
        {
            Splay(t,k);
            t->v+=a;
            t->son[0]->add+=a;
        }
        void Reverse(treap* &t,int k)  //翻转
        {
            Splay(t,k);
            treap* p=t->son[1];
            t->son[1]=&null;
            t->pushup();
            t->lazy=1;
            t->pushdown();
            Splay(t,k);
            t->son[1]=p;
            t->pushup();
        }
        void Insert(treap* &t,int x)  //插入
        {
            Splay(t,1);
            treap* p=NewNode(x);
            p->son[1]=t->son[1];
            p->pushup();
            t->son[1]=p;
            t->pushup();
            Size++;
        }
        void Remove(treap* &t)  删除
        {
            Splay(t,1);
            treap* next=t->son[1];
            t=next;
            t->pushdown();
            Size--;
        }
        void Move(treap* &t,int x)  //移动
        {
            if(x==1)
            {
                Splay(t,Size);
                treap* p=t->son[0];
                t->son[0]=&null;
                p->pushdown();
                Splay(p,1);
                t->son[1]=p;
                t->pushup();
            }
            else
            {
                Splay(t,1);
                treap* p=t->son[1];
                t->son[1]=&null;
                p->pushdown();
                Splay(p,Size-1);
                t->son[0]=p;
                t->pushup();
            }
        }
    };
    int N,M,K1,K2;
    int main()
    {
        int Case=0;
        while(scanf("%d%d%d%d",&N,&M,&K1,&K2)!=EOF)
        {
            if(!N&&!M&&!K1&&!K2) break;
            for(int i=1;i<=N;i++) scanf("%d",&A[i]);
            cnt=0;
            splaytree spt;
            spt.Build(spt.root,1,N);
            spt.Size=N;
            printf("Case #%d:
    ",++Case);
            while(M--)
            {
                char op[10];
                int x;
                scanf("%s",op);
                if(strcmp(op,"add")==0)
                {
                    scanf("%d",&x);
                    spt.Add(spt.root,K2,x);
                }
                else if(strcmp(op,"reverse")==0) spt.Reverse(spt.root,K1);
                else if(strcmp(op,"insert")==0)
                {
                    scanf("%d",&x);
                    spt.Insert(spt.root,x);
                }
                else if(strcmp(op,"delete")==0) spt.Remove(spt.root);
                else if(strcmp(op,"move")==0)
                {
                    scanf("%d",&x);
                    spt.Move(spt.root,x);
                }
                else
                {
                    spt.Splay(spt.root,1);
                    printf("%d
    ",spt.root->v);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python学习笔记-面向对象进阶复习小结
    python学习笔记-类的静态属性,类方法和静态方法
    python学习笔记-面向对象的继承、多态、封装
    python学习笔记-python简介
    python学习笔记-列表、元组字典
    python学习笔记-常用数据类型之字符串
    python学习笔记-函数,递归和内置函数
    python学习笔记-文件操作
    python学习笔记-迭代器与生成器
    python学习笔记-装饰器
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5652479.html
Copyright © 2011-2022 走看看