【BZOJ1552】[Cerc2007]robotic sort Splay
【BZOJ1552】[Cerc2007]robotic sort
Description
Input
输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。
Output
输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。
Sample Input
6
3 4 5 1 6 2
3 4 5 1 6 2
Sample Output
4 6 4 5 6 6
题解:继续复习Splay,本题问的是编号第i小的位置,那我们就直接先将编号排序,用排名来充当该物品新的编号,并用新编号建一个Splay,那么我们在查询的时候就只需要知道新编号为i的点在Splay中的位置就行了。然后区间反转什么的就简单了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=100010; struct node { int ch[2],fa,size,tag; }p[maxn]; struct item { int num,org; }it[maxn]; int n,root,v[maxn]; bool cmp(item a,item b) { if (a.num==b.num) return a.org<b.org; return a.num<b.num; } int readin() { int ret=0; char gc; while (gc< '0' ||gc> '9' ) gc=getchar(); while (gc>= '0' &&gc<= '9' ) ret=ret*10+gc- '0' ,gc=getchar(); return ret; } void pushup( int x) { p[x].size=p[p[x].ch[0]].size+p[p[x].ch[1]].size+1; } void pushdown( int x) { if (p[x].tag) { swap(p[x].ch[0],p[x].ch[1]); if (p[x].ch[0]) p[p[x].ch[0]].tag^=1; if (p[x].ch[1]) p[p[x].ch[1]].tag^=1; p[x].tag=0; } } void rotate( int x, int &k) { int y=p[x].fa,z=p[y].fa,d=(x==p[y].ch[1]); if (y==k) k=x; else p[z].ch[y==p[z].ch[1]]=x; p[x].fa=z,p[y].fa=x,p[y].ch[d]=p[x].ch[d^1]; if (p[x].ch[d^1]) p[p[x].ch[d^1]].fa=y; p[x].ch[d^1]=y; pushup(y),pushup(x); } void build( int l, int r, int last) { if (l>r) return ; int mid=l+r>>1; if (last) p[v[last]].ch[mid>last]=v[mid]; p[v[mid]].fa=v[last]; build(l,mid-1,mid),build(mid+1,r,mid); pushup(v[mid]); } int find( int x, int y) { pushdown(x); if (y==p[p[x].ch[0]].size+1) return x; if (y<=p[p[x].ch[0]].size) return find(p[x].ch[0],y); else return find(p[x].ch[1],y-p[p[x].ch[0]].size-1); } int qrank( int x) { if (x==root) return p[p[x].ch[0]].size+1; int ret=qrank(p[x].fa); pushdown(x); if (x==p[p[x].fa].ch[0]) ret-=p[p[x].ch[1]].size+1; else ret+=p[p[x].ch[0]].size+1; return ret; } void splay( int x, int &k) { while (x!=k) { int y=p[x].fa,z=p[y].fa; if (y!=k) { if ((x==p[y].ch[0])^(y==p[z].ch[0])) rotate(x,k); else rotate(y,k); } rotate(x,k); } } int main() { scanf( "%d" ,&n); int i; for (i=1;i<=n;i++) it[i].num=readin(),it[i].org=i; sort(it+1,it+n+1,cmp); for (i=1;i<=n;i++) v[it[i].org+1]=i; v[1]=n+1,v[n+2]=n+2; root=v[(n+3)>>1]; build(1,n+2,0); for (i=1;i<n;i++) { int temp=qrank(i); printf( "%d " ,temp-1); splay(find(root,i),root); splay(find(root,temp+1),p[root].ch[1]); p[p[p[root].ch[1]].ch[0]].tag^=1; } printf( "%d" ,n); return 0; } |
| 欢迎来原网站坐坐! >原文链接<
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术