Hdu 4453 Looploop(环上的Splay操作)

来源:互联网 发布:360压缩 mac 编辑:程序博客网 时间:2024/06/05 02:10

传送门:Hdu 4453 Looploop


题意:给你序列(形成一个环),有六种操作
1.指定一个元素,这个元素之后的k2个元素加上x
2.指定一个元素,这个元素之后的k2个元素翻转
3.在指定元素的右端插入一个数
4.删除这个元素,然后把指针移到下一个
5.把指针往左或者往右移动(x=1移到左边,x=2移到右边)
6.输出现在指针所指的数


思路:破环成链,利用Splay
指针记录的是Splay中的下标
操作一的处理,判断当前这个元素之后是否还存在k2个元素(先判断这个元素的Rank值,然后查询第Rank+k2大),如不存在,把前面x个切掉接到后面
操作二同理,后面的操作都是普通的Splay


#include<bits/stdc++.h>using namespace std;#define INF 0x3f3f3f3f#define key_value ch[ ch[root][1] ][0]const int N=3e5+100;int n,k1,k2,size[N],val[N],tot,a[N],Pointer,ch[N][2],root,fa[N];int addv[N],rev[N];void Newnode(int &now,int father,int k){    now=++tot;    val[now]=k,ch[now][0]=ch[now][1]=0,fa[now]=father;    size[now]=1,addv[now]=rev[now]=0;}void pushdown(int x){    int ls=ch[x][0],rs=ch[x][1];    if(addv[x]){        if(ls)            val[ls]+=addv[x],addv[ls]+=addv[x];        if(rs)            val[rs]+=addv[x],addv[rs]+=addv[x];        addv[x]=0;    }    if(rev[x]){        if(ls)  rev[ls]^=1;        if(rs)  rev[rs]^=1;        swap(ch[x][0],ch[x][1]);        rev[x]=0;    }}void pushup(int x){    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}void build(int &now,int l,int r,int father){    if(l>r)        return ;    int m=(l+r)>>1;    Newnode(now,father,a[m]);    build(ch[now][0],l,m-1,now);    build(ch[now][1],m+1,r,now);    pushup(now);}void init(){    root=tot=0;    Newnode(root,0,-INF);    Newnode(ch[root][1],root,-INF);//头尾各加入一个空位    build(key_value,1,n,ch[root][1]);    pushup(ch[root][1]);    pushup(root);}//旋转,kind为1为右旋,kind为0为左旋void Rotate(int x,int kind){    int y=fa[x];    ch[y][!kind]=ch[x][kind];    fa[ch[x][kind]]=y;    //如果父节点不是根结点,则要和父节点的父节点连接起来    if(fa[y])        ch[fa[y]][ch[fa[y]][1]==y]=x;    fa[x]=fa[y];    ch[x][kind]=y;    fa[y]=x;    pushup(y);}//Splay调整,将根为now的子树调整为goalvoid Splay(int now,int goal){    pushdown(now);    while(fa[now]!=goal){        pushdown(fa[fa[now]]),pushdown(fa[now]),pushdown(now);        if(fa[ fa[now] ]==goal)            Rotate(now,ch[ fa[now] ][0]==now);        else{            int pre=fa[now],kind=ch[ fa[pre] ][0]==pre; //左儿子为1,右儿子为0            if(ch[pre][kind]==now){ //两个方向不同                Rotate(now,!kind);                Rotate(now,kind);            }            else{   //两个方向相同                Rotate(pre,kind);                Rotate(now,kind);            }        }    }    if(goal==0) root=now;    pushup(now);}int get_kth(int x,int k){    pushdown(x);    int num=size[ch[x][0]]+1;    if(num==k)        return x;    else if(num>k)        return get_kth(ch[x][0],k);    return get_kth(ch[x][1],k-num);}int get_min(int x){    pushdown(x);    x=ch[x][1];   pushdown(x);    while(ch[x][0])        x=ch[x][0],pushdown(x);    return x;}int get_max(int x){    pushdown(x);    x=ch[x][0];    pushdown(x);    while(ch[x][1])        x=ch[x][1],pushdown(x);    return x;}void Add(int x,int k,int distance){    Splay(x,0);    //size[ch[x][0]]表示这个x的Rank,size[x]-2表示总共有多少个    if(size[ch[x][0]]+distance-1<=size[x]-2){        int tmp=size[ch[x][0]]+distance-1;        Splay(get_max(root),0);        Splay(get_kth(root,tmp+2),root);        val[key_value]+=k,addv[key_value]+=k;        pushup(ch[root][1]),pushup(root);    }    else{        //把前面的切割掉        int remain=size[ch[x][0]]+distance-1-(size[x]-2);//开头有多少个        Splay(1,0),Splay(get_kth(root,remain+2),root);        int tmp=key_value;        key_value=0,pushup(ch[root][1]),pushup(root);        Splay(get_kth(root,size[root]-1),0),Splay(2,root);        key_value=tmp,fa[key_value]=ch[root][1];        pushup(ch[root][1]),pushup(root);        Splay(x,0);        Splay(get_max(x),0),Splay(2,root);        val[key_value]+=k,addv[key_value]+=k;    }}void Reverse(int x,int distance){    Splay(x,0);    //size[ch[x][0]]表示这个x的Rank,size[x]-2表示总共有多少个    if(size[ch[x][0]]+distance-1<=size[x]-2){        int tmp=size[ch[x][0]]+distance-1;        Splay(get_max(root),0);        Pointer=get_kth(root,tmp+1);        Splay(get_kth(root,tmp+2),root);        rev[key_value]^=1;        pushup(ch[root][1]),pushup(root);    }    else{        //把前面的切割掉        int remain=size[ch[x][0]]+distance-1-(size[x]-2);//开头有多少个        Splay(1,0),Splay(get_kth(root,remain+2),root);        Pointer=get_kth(root,remain+1);        int tmp=key_value;        key_value=0,pushup(ch[root][1]),pushup(root);        Splay(get_kth(root,size[root]-1),0),Splay(2,root);        key_value=tmp,fa[key_value]=ch[root][1];    //拼接        pushup(ch[root][1]),pushup(root);        Splay(x,0);        Splay(get_max(x),0),Splay(2,root);        rev[key_value]^=1;    }}void Insert(int x,int k){    Splay(x,0);    Splay(get_min(x),root);    Newnode(key_value,ch[root][1],k);    pushup(ch[root][1]),pushup(root);}//去根void remove(){    int m=get_max(root);    Splay(m,root);    ch[m][1]=ch[root][1];    fa[ch[root][1]]=m;    root=m;    fa[root]=0;    pushup(root);}void Delete(int x){    Splay(x,0);    Pointer=get_min(x);//找到后继    remove();    if(val[Pointer]==-INF)        Pointer=get_kth(root,2);}void Move(int x,int k){    Splay(x,0);    if(k==-1){        Pointer=get_max(root);        if(val[Pointer]==-INF){  //原来的Pointer是第一个            Splay(2,0);            Pointer=get_max(root);        }    }    else{        Pointer=get_min(root);        if(val[Pointer]==-INF)  //到开头            Pointer=get_kth(root,2);    }}void Query(int x){    Splay(x,0);    printf("%d\n",val[x]);}char str[10];int main(){    int m,x,case1=1;    while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF){        if(n==0&&m==0&&k1==0&&k2==0)            break;        printf("Case #%d:\n",case1++);        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        init();        Pointer=get_kth(root,2);//刚开始为第2大        for(int i=1;i<=m;i++){            scanf("%s",str);            if(str[0]=='a'){                scanf("%d",&x);                Add(Pointer,x,k2);            }            else if(str[0]=='r'){                Reverse(Pointer,k1);            }            else if(str[0]=='i'){                scanf("%d",&x);                Insert(Pointer,x);            }            else if(str[0]=='d')                Delete(Pointer);            else if(str[0]=='m'){                scanf("%d",&x);                if(x==1)                    Move(Pointer,-1);                else                    Move(Pointer,1);            }            else                Query(Pointer);        }    }    return 0;}
0 0
原创粉丝点击