【bzoj3223】Tyvj 1729 文艺平衡树 Splay
2015-12-08 20:10
281 查看
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1Input
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n
Output
输出一行n个数字,表示原始序列经过m次变换后的结果Sample Input
[code]5 3 1 3 1 3 1 4
Sample Output
[code]4 3 2 1 5
HINT
N,M<=100000Source
平衡树splay区间操作,蛋疼了我半天…………
每个节点存儿子、父亲、出现次数、子树大小、权值。其中权值为该节点代表的序列的位置的那个值。
权值并不用来维护平衡树的性质,维护平衡树的性质的那个权值(也就是下标)并不存下来。旋转并不会破坏这个性质。
这样就可以像寻找第K大那样找到序列中某一个点了。
翻转区间:交换左右儿子的指针。
代码:
[code]#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int SZ = 1000010; const int INF = 1000000010; struct node{ node *ch[2],*f; int sz,cnt,v,x; bool flag; void maintain() { sz = ch[0] -> sz + ch[1] -> sz + cnt; } void setc(node *x,int d) { (ch[d] = x) -> f = this; } int cmp(int x) { if(x == v) return -1; return x < v ? 0 : 1; } int dir() { return f -> ch[1] == this; } void pushdown(); }T[SZ], *root, *null; int Tcnt = 0; void node::pushdown() { if(flag) { flag = 0; if(ch[1] != null) ch[1] -> flag ^= 1; if(ch[0] != null) ch[0] -> flag ^= 1; swap(ch[0],ch[1]); } } node* newnode(int v,node *f) { node *k = T + (Tcnt ++); k -> ch[1] = k -> ch[0] = null; k -> v = v; k -> sz = k -> cnt = 1; k -> flag = 0; k -> f = f; return k; } void rotate(node *p) { p -> f -> pushdown(); p -> pushdown(); node *fa = p -> f; int d = p -> dir(); fa -> f -> setc(p,fa -> dir()); fa -> setc(p -> ch[d ^ 1],d); fa -> maintain(); p -> setc(fa,d ^ 1); p -> maintain(); if(fa == root) root = p; } void splay(node *p,node *rt = null) { while(p -> f != rt) { p -> pushdown(); if(p -> f -> f == rt) rotate(p); else { if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p); else rotate(p),rotate(p); } } } node* find(node *p,int k) { while(p != null) { p -> pushdown(); int l = p -> ch[0] -> sz + 1; int r = p -> ch[0] -> sz + p -> cnt; if(l <= k && k <= r) return p; if(k > r) k -= r,p = p -> ch[1]; else p = p -> ch[0]; } } void reverse(node *p,int l,int r) { l ++; r ++; node* pre = find(root,l - 1); node* suf = find(root,r + 1); splay(pre); splay(suf,root); root -> ch[1] -> ch[0] -> flag ^= 1; } void build(node* &p,int l,int r,node *fa) { if(l > r) return ; int mid = (l + r) >> 1; p = newnode(mid,fa); build(p -> ch[0],l,mid - 1,p); build(p -> ch[1],mid + 1,r,p); p -> maintain(); } int n,m; void init() { null = newnode(-INF,null); null -> sz = null -> cnt = 0; root = newnode(-INF,null); root -> ch[1] = newnode(INF,root); build(root -> ch[1] -> ch[0],1,n,root -> ch[1]); root -> ch[1] -> maintain(); root -> maintain(); } int main() { scanf("%d%d",&n,&m); init(); while(m --) { int l,r; scanf("%d%d",&l,&r); reverse(root,l,r); } for(int i = 1;i <= n;i ++) printf("%d ",(find(root,i + 1)) -> v); return 0; }
相关文章推荐
- ant安装时
- AsyncTask的简单使用
- pdf加水印,文字和图片,超链接, java itext, 这里有你想要的一切
- 工作中遇到的一个多线程下导致RCW无法释放的问题
- Android Java 动态代理应用
- 【BZOJ3585】mex
- 有用资源分享
- 一套代码多平台发布 私图(私图大赏)APP成功上线
- POJ3249 Test for Job(拓扑排序+dp)
- Linux 的popen函数
- ArrayList排序sort()方法
- 使用Filter控制用户登录权限
- POJ_P1273 Drainage Ditches(模板题+网络流)
- DOS批处理对人脸库进行分类
- UIImage的属性整理
- 高逼格saas服务的文档展示
- Android 定义自己的Application
- 根据两点经纬度计算距离
- wayland应用程序中touch事件的实现
- 更改oracle字符集