Hdu 4453 Looploop(环上的Splay操作)
2016-08-25 18:59
337 查看
传送门:Hdu 4453 Looploop
题意:给你序列(形成一个环),有六种操作
1.指定一个元素,这个元素之后的k2个元素加上x
2.指定一个元素,这个元素之后的k2个元素翻转
3.在指定元素的右端插入一个数
4.删除这个元素,然后把指针移到下一个
5.把指针往左或者往右移动(x=1移到左边,x=2移到右边)
6.输出现在指针所指的数
思路:破环成链,利用Splay
指针记录的是Splay中的下标
操作一的处理,判断当前这个元素之后是否还存在k2个元素(先判断这个元素的Rank值,然后查询第Rank+k2大),如不存在,把前面x个切掉接到后面
操作二同理,后面的操作都是普通的Splay
题意:给你序列(形成一个环),有六种操作
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 ,val ,tot,a ,Pointer,ch [2],root,fa ; int addv ,rev ; 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的子树调整为goal void 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; }
相关文章推荐
- 解密SparkStreaming运行机制和架构进阶之Job和容错
- ELK在linux部署安装(一)
- nginx_connect&request
- Tomcat源码解析(九):配置文件读取
- centos安装中文语言包
- 远程登录linux不用输入密码的方法
- Tomcat源码解析(八):Host
- Tomcat的 虚拟目录&虚拟主机 配置放方法
- PowerShell正则表达式(一) 定义模式
- tomcat源码解析(七):server和service
- linux文件特殊权限:SUID,SGID,SBIT
- Linux C 调用脚本
- centOS搭建linux驱动开发环境
- 让你快速解开对copy、mutableCopy,深复制和浅复制的疑惑
- 学习hadoop需要具备基础知识
- 玩转centos7和docker
- Linux常用命令
- Linux shell中的&&和||
- Apache commons-io 工具类的使用
- Linux进程之task_struct结构体