hdu1890 Robotic Sort Splay树,区间反转,lazy标记
来源:互联网 发布:怎么让淘宝店铺关掉 编辑:程序博客网 时间:2024/05/29 19:55
对spaly的一些理解:在Splay和Rotate两个操作对树中元素的大小关系是没有影响的,但会影响一些记录如sum值。
这题就以id为key建树,区间反转用rev标记,标记下传时仅交换指向左右儿子的指针,反转后树中元素的大小关系发生了改变。
删除根节点时将右子树中序遍历的第一个点(最小的点)伸展到根节点下,这样右子树的左子树为空。找第一个点时需要pushDown。
#include<iostream>#include<cstring>#include<cstdio>#include<ostream>#include<istream>#include<algorithm>#include<queue>#include<string>#include<cmath>#include<set>#include<map>#include<stack>#include<vector>#define fi first#define se second#define ll long long#define pii pair<int,int>#define inf (1<<30)#define eps 1e-8#define pb push_backusing namespace std;const int maxn=110005;int n;int d[maxn];struct Node{ int w,p; int id; bool operator<(const Node& u)const { if(w==u.w) return id<u.id; return w<u.w; }}block[maxn];struct SplayTree{ int son[maxn][2],pre[maxn]; int sum[maxn]; int rev[maxn]; int rt,sz; void init() { sz=rt=0; memset(rev,0,sizeof(rev)); son[rt][0]=son[rt][1]=0; sum[rt]=0; } void pushDown(int p) { if(rev[p]) { int ls=son[p][0]; int rs=son[p][1]; rev[ls]=(rev[ls]+1)%2; rev[rs]=(rev[rs]+1)%2; son[p][0]=rs; son[p][1]=ls; rev[p]=0; } } void Rotate(int x,int c) { int y=pre[x]; pushDown(x); pushDown(y); son[y][!c]=son[x][c]; pre[son[x][c]]=y; pre[x]=pre[y]; if(pre[x]) son[pre[y]][son[pre[y]][1]==y]=x; son[x][c]=y; pre[y]=x; pushUp(y); pushUp(x); } void pushUp(int x) { sum[x]=sum[son[x][0]]+sum[son[x][1]]+1; } void Splay(int x,int goal) { pushDown(x); while(pre[x]!=goal) { if(pre[pre[x]]==goal) { pushDown(pre[x]); pushDown(x); if(son[pre[x]][0]==x) Rotate(x,1); else Rotate(x,0); } else { int y=pre[x],z=pre[y]; pushDown(z); pushDown(y); pushDown(x); if(son[z][0]==y) { if(son[y][0]==x) { Rotate(y,1); Rotate(x,1); } else { Rotate(x,0); Rotate(x,1); } } else { if(son[y][1]==x) { Rotate(y,0); Rotate(x,0); } else { Rotate(x,1); Rotate(x,0); } } } } pushUp(x); if(goal==0) rt=x; } void newNode(int& rt,int k) { rt=++sz; son[rt][0]=son[rt][1]=0; block[k].id=k; block[k].w=d[k]; block[k].p=rt; } void build(int& rt,int l,int r,int p) { int m=(l+r)/2; newNode(rt,m); sum[rt]=r-l+1; pre[rt]=p; if(l<=m-1) build(son[rt][0],l,m-1,rt); if(m+1<=r) build(son[rt][1],m+1,r,rt); } void Delete() { if(son[rt][1]==0 || son[rt][0]==0) { rt=son[rt][0]+son[rt][1]; pre[rt]=0; } else { int x=son[rt][1]; while(true) { pushDown(x); if(son[x][0]) x=son[x][0]; else break; } Splay(x,rt); son[son[rt][1]][0]=son[rt][0]; sum[son[rt][1]]+=sum[son[rt][0]]; pre[son[rt][0]]=son[rt][1]; rt=son[rt][1]; pre[rt]=0; } } void work() { for(int i=1;i<=n;i++) { Splay(block[i].p,0); if(i==n) printf("%d\n",i+sum[son[rt][0]]); else printf("%d ",i+sum[son[rt][0]]); rev[son[rt][0]]^=1; Delete(); } }} spt;int main(){ while(~scanf("%d",&n)&&n) { for(int i=1;i<=n;i++) scanf("%d",&d[i]); spt.init(); spt.build(spt.rt,1,n,0); sort(block+1,block+n+1); spt.work(); } return 0;}
0 0
- hdu1890 Robotic Sort Splay树,区间反转,lazy标记
- hdu1890 Robotic Sort splay+懒惰标记+翻转
- hdu1890 Robotic Sort(Splay)
- Splay hdu1890 Robotic Sort
- HDU1890 Robotic Sort(Splay)
- hdu1890 Robotic Sort (splay+区间翻转单点更新)
- [hdu1890 Robotic Sort]Splay Tree
- 伸展树 - hdu1890 Robotic Sort
- HDU1890 Robotic Sort(slpay,区间旋转)
- HDU 1890 Robotic Sort 伸展树的区间反转与延迟标记
- HDU1890 Robotic Sort
- HDU 1890 Robotic Sort [平衡树splay 区间翻转]
- 【HDU】1890 Robotic Sort 翻转区间【splay】
- hdu 1890 Robotic Sort splay区间旋转
- HDU 1890 Robotic Sort(Splay 区间翻转)
- [BZOJ1552]robotic sort SPlay区间翻转
- Robotic Sort hdu1890 (伸展树翻转+删根)
- hdu 1890 Robotic Sort (Splay树)
- PHP CLI模式下的多进程应用
- 启动页面加载
- Java并发教程(Oracle官方资料)
- JAVA_SE系列:06.文档注释和API文档
- OpenStack之日志
- hdu1890 Robotic Sort Splay树,区间反转,lazy标记
- 为什么父类指针可以指向子类反之则不行?
- 使用 NSIS 制作软件安装包
- AS3 URLRequest相关,浏览器请求头MIME类型引发的问题
- Android 语言切换实现(就是这么简单)
- 分享python的几个学习资源
- module_init的加载和释放
- Binary Tree Right Side View
- 数据结构学习之路-第二章:线性表的顺序表示与实现