HDU3487 Play with Chain splay 区间反转
HDU3487 splay最核心的功能是将平衡树中的节点旋转到他的某个祖先的位置,并且维持平衡树的性质不变。
两个操作(数组实现)
cut l,r, c把[l,r]剪下来放到剩下序列中第c个后面的位置.
flip l r 把[l,r]翻转(lazy标记,每次交换左右节点)
cut思路:把l-1旋到根,r+1旋到根的右节点,取下这一段;在剩下的序列中找到c,c+1的位置,把c旋到根,c+1旋到右节点,插入。
由平衡树性质易证得是对的(中序遍历恒定)
flip思路:把l-1旋到根,r+1旋到右节点,打上lazy标记。
调数据结构的代码 是坠痛苦滴 不过一个人的命运当然要靠自我奋斗
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=400000; int Root,n,m;
struct Node
{
int val,cnt,size;
bool rev;
int father;int lson;int rson;
Node(int v,int c,int fa,int l,int r)
{this->val=v;this->cnt=c;this->father=fa;this->lson=l;this->rson=r;rev=false;}
}tren[maxn]=Node(0,0,0,0,0); queue<int> memq; int newnode()
{
int loc=memq.front();memq.pop();
return loc;
} void dele(int loc)
{
memq.push(loc);
return ;
} void pushdown(int x)
{
if(x==0)return ;
if(tren[x].rev)
{
tren[x].rev=false;
swap(tren[x].lson,tren[x].rson);
if(tren[x].lson!=0)tren[tren[x].lson].rev=!tren[tren[x].lson].rev;
if(tren[x].rson!=0)tren[tren[x].rson].rev=!tren[tren[x].rson].rev;
}
} void update(int x)
{
tren[x].size=tren[x].cnt;
if(tren[x].lson!=0)tren[x].size+=tren[tren[x].lson].size;
if(tren[x].rson!=0)tren[x].size+=tren[tren[x].rson].size;
} void zig(int x)
{
int fa=tren[x].father;
pushdown(fa);pushdown(x);
if(tren[tren[fa].father].lson==fa){tren[tren[fa].father].lson=x;}
else {tren[tren[fa].father].rson=x;}
tren[x].father=tren[fa].father;
tren[fa].father=x;
tren[fa].lson=tren[x].rson;
tren[tren[x].rson].father=fa;
tren[x].rson=fa;
update(tren[x].rson);update(x);update(tren[x].father);
//swap(tren[fa],tren[x]);
} void zag(int x)
{
int fa=tren[x].father;
pushdown(fa);pushdown(x);
if(tren[tren[fa].father].lson==fa){tren[tren[fa].father].lson=x;}
else {tren[tren[fa].father].rson=x;}
tren[x].father=tren[fa].father;
tren[fa].father=x;
tren[fa].rson=tren[x].lson;
tren[tren[x].lson].father=fa;
tren[x].lson=fa;
update(tren[x].lson);update(x);update(tren[x].father);
//swap(tren[fa],tren[x]);
} void splay(int root,int now)//核心
{
if(root==0||now==0)return ;
int end=tren[root].father;
while(tren[now].father!=end)
{
if(tren[now].father==root)
{
if(tren[tren[now].father].lson==now)zig(now);
else zag(now);
return ;
}
int fa=tren[now].father;int grand=tren[fa].father;
if(tren[grand].lson==fa)
{
if(tren[fa].lson==now){zig(fa);zig(now);continue;}
else{zag(now);zig(now);continue;}
}
else{
if(tren[fa].rson==now){zag(fa);zag(now);continue;}
if(tren[fa].lson==now){zig(now);zag(now);continue;}
}
}
return ;
} int insert(int fa,int root,int value)
{
int ans;
pushdown(root);
if(root==0)
{
root=newnode();
tren[root]=Node(value,1,fa,0,0);
update(root);
ans= root;
//splay(1,root);
}
if(tren[root].val==value)
{tren[root].cnt++;update(root);ans=0;}
if(tren[root].val>value)
{
if(tren[root].lson==0)
{
tren[root].lson=newnode();
tren[tren[root].lson]=Node(value,1,root,0,0);
update(tren[root].lson);
// splay(1,tren[root].lson);
ans= tren[root].lson;
}
else ans= insert(root,tren[root].lson,value);
}
else
{
if(tren[root].rson==0)
{
tren[root].rson=newnode();
tren[tren[root].rson]=Node(value,1,root,0,0);
update(tren[root].rson);
//splay(1,tren[root].rson);
ans= tren[root].rson;
}
else ans= insert(root,tren[root].rson,value);
}
update(root);
return ans;
} int access(int root,int key)
{
pushdown(root);
if(tren[root].val==key)return root;
if(tren[root].val<key)return access(tren[root].rson,key);
else return access(tren[root].lson,key);
} int Max(int root)
{
pushdown(root);
if(root==0||tren[root].rson==0)return root;
else return Max(tren[root].rson);
} int join(int l,int r)
{
if(l==0)return r;
if(r==0)return l;
int max=Max(l);
splay(l,max);
tren[max].rson=r;
return max;
} void erase(int root,int key)
{
int now=access(root,key);
int fa=tren[now].father;
if(tren[now].cnt>1){tren[now].cnt--;return ;}
else
{
if(tren[fa].lson==now){tren[fa].lson=join(tren[now].lson,tren[now].rson);}
else{tren[fa].rson=join(tren[now].lson,tren[now].rson);}
}
return ;
} int getKth(int root,int k)
{
while(root!=0&&k<=tren[root].size)
{
pushdown(root);
int ls=tren[root].lson,rs=tren[root].rson;
if(ls!=0&&k<=tren[ls].size){root=ls;continue;}
k-=tren[root].cnt;
if(ls!=0)k-=tren[ls].size;
if(k<=0){return root;}
root=rs;
}
} void maintain(int now,int val)
{
while(now!=0)
{
tren[now].size+=val;
now=tren[now].father;
}
}
vector<int>ans;
void print( int root)
{
if(root==0)return ;
pushdown(root);
print(tren[root].lson);
if(tren[root].val<=n&&tren[root].val>=1)ans.push_back(tren[root].val);
print(tren[root].rson);
} int main()
{freopen("t.txt","r",stdin);
freopen("1.txt","w",stdout); while(scanf("%d%d",&n,&m))
{
while(!memq.empty())memq.pop();
for(int i=2;i<min(n*2,400000);i++)
memq.push(i);
if(n<=0||m<=0)return 0;
tren[1]=Node(0,1,0,0,0);
update(1);
Root=1;
for(int i=1;i<=n+1;i++)
{
int newl=insert(0,Root,i);
splay(Root, newl);
Root=newl;
}
for(int i=1;i<=m;i++)
{
char ss[10];
scanf("%s",ss);
if(ss[0]=='C')
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int klo=getKth(Root,a);
splay(Root,klo);
Root=klo;
klo=getKth(Root,b+2);
splay(tren[Root].rson,klo);
int tre=tren[klo].lson;
maintain(tren[tre].father,tren[tre].size*(-1));
tren[klo].lson=0;
klo=getKth(Root,c+1);
splay(Root,klo);
Root=klo;
klo=getKth(Root,c+2);
splay(tren[Root].rson,klo);
tren[klo].lson=tre;
tren[tre].father=klo;
maintain(tren[tre].father,tren[tre].size);
}
if(ss[0]=='F')
{
int a,b;
scanf("%d%d",&a,&b);
int klo=getKth(Root,a);
splay(Root,klo);
Root=klo;
klo=getKth(Root,b+2);
splay(tren[Root].rson,klo);
tren[ tren[tren[Root].rson].lson].rev=!tren[ tren[tren[Root].rson].lson].rev;
}
}
ans.clear();
print (Root);
for(int i=0;i<ans.size()-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[ans.size()-1]);
}
return 0;
}
HDU3487 Play with Chain splay 区间反转的更多相关文章
- 算法模板——splay区间反转 2
实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没 ...
- HDU3487 Play With Chain [Splay]
题目传送门 题目描述 Problem Description YaoYao is fond of playing his chains. He has a chain containing n dia ...
- 算法模板——splay区间反转 1
实现的功能:将序列区间反转,并维护 详见BZOJ3223 var i,j,k,l,m,n,head,a1,a2:longint; s1:ansistring; a,b,c,d,fat,lef,rig: ...
- Splay 区间反转
同样的,我们以一道题来引入. 传送门 这次的任务比较少,只要求进行区间反转.区间反转? 这个好像用啥都是O(n)的吧……(这次vector,set也救不了你了) 我们来使用splay解决这个问题.我们 ...
- hdu 1890 Robotic Sort(splay 区间反转+删点)
题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...
- HDU-3487 Play with Chain Splay tee区间反转,移动
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 对于一个数列有两种操作:1.CUT a b c,先取出a-b区间的数,然后把它们放在取出后的第c ...
- HDU--3487 Play with Chain (Splay伸展树)
Play with Chain Problem Description YaoYao is fond of playing his chains. He has a chain containing ...
- HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Li ...
- [bzoj3223]文艺平衡树(splay区间反转模板)
解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include< ...
随机推荐
- 牛客多校Round 10
咕咕咕.... 去烽火台和兵马俑了
- C/C++野指针
野指针: 野指针不同于空指针,空指针是指一个指针的值为null,而野指针的值并不为null,野指针会指向一段实际的内存,只是它指向哪里我们并不知情,或者是它所指向的内存空间已经被释放,所以在实际使用的 ...
- MyBatis 的基本要素—核心配置文件
MyBatis 核心配置文件( mybatis-config.xml),该文件配置了 MyBatis 的一些全局信息,包含数据库连接信息和 MyBatis 运行时所需的各种特性,以及设置和影响 MyB ...
- linux tload-显示系统负载状况
推荐:更多linux 性能监测与优化 关注:linux命令大全 tload命令以图形化的方式输出当前系统的平均负载到指定的终端.假设不给予终端机编号,则会在执行tload指令的终端机显示负载情形. 语 ...
- 洛谷 4302 BZOJ 1090 SCOI2003 字符串折叠 UVA1630 Folding(输出方案版)
[题解] 区间DP. 设f[i][j]表示i~j的最小代价.再枚举中间点k,很容易想到转移方程为f[i][j]=min(f[i][j],f[i][k]+f[k][j]),同时如果i~k可以通过重复获 ...
- BZOJ 3648 寝室管理
[题解] GDOI2016 Day2T3 如果给出的数据是一棵树那么皆大欢喜直接点分治就好了,用树状数组维护大于x的数的个数.如果是一棵基环树,我们先断掉环上的一条边,然后跑点分治:再加上经过这条边的 ...
- Spring 使用注解注入 学习(四)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- shrink&split
shrink将分片数按因子缩减.hard link segment文件.因缩减前后hash一致,不需要rehash.如:0 ,1 , 2, 3, 4, 5, 6, 7, 8.9个分片缩减成3个:0 [ ...
- 使用 XMLHttpRequest实现Ajax
[XMLHttpRequest的概述] 1.XMLHttpRequest最早是在IE5中以ActiveX组件的形式实现的.非W3C标准 2.创建XMLHttpRequest对象(由于非标准所以实现方法 ...
- [USACO06FEB]数字三角形
题目描述 FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N ...