您的位置:首页 > 运维架构

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

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: