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
- Hdu 4453 Looploop(环上的Splay操作)
- hdu-4453-Looploop-splay
- 【HDU】4453 Looploop 【splay】
- 【HDU 4453】 Looploop(Splay)
- hdu 4453 Looploop(splay)
- hdu 4453 Looploop 伸展树splay
- HDU-4453 Looploop(Splay树)
- HDU 4453 Looploop (splay tree)
- HDOJ 4453 Looploop Splay
- hdu 4453 Looploop(Splay或者三个双端队列)
- 【splay tree】 HDOJ 4453 Looploop
- HDU 4453 Looploop(SplayTree)
- HDU 4453 Looploop (Treap)
- hdu 4453 Looploop (伸展树)
- hdu 4453 Looploop(伸展树)
- [hdu4453]looploop [treap/splay]
- HDU 4453 Looploop (双向链表)
- Splay tree的splay操作
- 居民身份证验证原理
- c++继承与派生
- Mac环境下对android app抓包
- Java异常之数字转换异常--java.lang.NumberFormatException
- Object类的输出
- Hdu 4453 Looploop(环上的Splay操作)
- java基础学习——Java添加事件监听的四种方法代码实例
- linux网络工具iproute2的使用简介
- Lucene的深度分页支持
- 网易大学课程
- poj 1321 棋盘问题
- 欧拉角
- MySQL的查询日志操作
- dispatch_semaphore_signal和dispatch_semaphore_wait信号量