1552: [Cerc2007]robotic sort
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 806 Solved: 329
[Submit][Status][Discuss]
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
HINT
Source
Solution
Splay基本操作...
我们首先对给出的序列排序,第一关键字是编号,第二关键字是时间戳,然后用splay去维护这个有顺序的序列就可以了
或者可以考虑维护min和pos
Splay要常写!调的跟*一样慢
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') {ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x;
}
#define MAXN 100010
int N,pos[MAXN];
struct Node{int id,t;}a[MAXN];
inline bool cmp(Node A,Node B) {return A.id==B.id? A.t<B.t:A.id<B.id;}
namespace SplayTree
{
int size[MAXN],root,sz,fa[MAXN],son[MAXN][]; bool rev[MAXN];
#define ls(x) son[x][0]
#define rs(x) son[x][1]
inline void Update(int now) {size[now]=size[ls(now)]+size[rs(now)]+;}
inline void PushDown(int now)
{
if (!rev[now]) return;
rev[ls(now)]^=; rev[rs(now)]^=; swap(ls(now),rs(now)); rev[now]=;
}
inline bool Right(int now) {return son[fa[now]][]==now;}
inline void rotate(int now)
{
PushDown(fa[now]); PushDown(now);
int f=fa[now],gf=fa[f],wh=Right(now);
son[f][wh]=son[now][wh^]; fa[son[f][wh]]=f;
fa[f]=now; son[now][wh^]=f; fa[now]=gf;
if (gf) son[gf][son[gf][]==f]=now;
Update(f); Update(now);
}
inline void splay(int now,int tar)
{
for (int f; (f=fa[now])!=tar; rotate(now))
if (fa[f]!=tar) rotate(Right(now)==Right(f)? f:now);
if (!tar) root=now;
}
inline int GetX(int k)
{
int x=root;
while ()
{
PushDown(x);
if (k<=size[ls(x)]) x=ls(x);
else if (k==size[ls(x)]+) return x;
else k-=size[ls(x)]+,x=rs(x);
}
return -;
}
inline int GetK(int x) {splay(x,); return size[ls(x)];}
inline int BuildTree(int l,int r,int last)
{
if (r<l) return ;
int mid=(l+r)>>,now=++sz;
pos[a[mid].id]=now; fa[now]=last;
int lson=BuildTree(l,mid-,now),rson=BuildTree(mid+,r,now);
son[now][]=lson; son[now][]=rson;
Update(now);
return now;
}
inline void Reverse(int l,int r) {splay(l,),splay(r,l); rev[ls(rs(root))]^=;}
inline void Init() {root=BuildTree(,N+,);}
}
int main()
{
N=read();
for (int i=,t=; i<=N+; i++) a[i].id=read(),a[i].t=++t;
a[].id=; a[N+].id=N+;
stable_sort(a+,a+N+,cmp);
for (int i=; i<=N; i++) a[a[i+].t+].id=i;
// for (int i=1; i<=N+2; i++) printf("%d ",a[i].id); puts("");
SplayTree::Init();
for (int i=; i<=N; i++)
{
int loc=SplayTree::GetK(pos[i]);
int x=SplayTree::GetX(i),y=SplayTree::GetX(loc+);
// printf("%d %d\n",x,y);
SplayTree::Reverse(x,y);
printf("%d%c",loc,i!=N? ' ':'\n');
}
return ;
}
和char哥,龙哥,连坐调splay...感觉智障++