P3165 [CQOI2014] 排序机械臂
题意
有一个序列 \(P=p_1,p_2,\dots,p_n\),第一次找出最小值的位置 \(a_1\),翻转 \([1,a_1]\),第二次找到次小值得位置 \(a_2\),反转 \([2,a_2]\),以此类推。要求输出 \(a_1,a_2,\dots,a_n\)。
\(n\le10^5,p_i\le10^7\)。
思路
直接按照题意模拟即可,用 \(Splay\) 维护序列。
代码
// Problem: P3165 [CQOI2014] 排序机械臂
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3165
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
namespace IO{
template<typename T>
inline void read(T&x){
x=0;char c=getchar();bool f=0;
while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
f?x=-x:0;
}
template<typename T>
inline void write(T x){
if(x==0){putchar('0');return ;}
x<0?x=-x,putchar('-'):0;short st[50],top=0;
while(x) st[++top]=x%10,x/=10;
while(top) putchar(st[top--]+'0');
}
inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
inline void write(char c){putchar(c);}
inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
const int maxn=100010,inf=1000000000;
int n,a[maxn],wz[maxn];
struct PX{
int val,id;
bool operator<(const PX t)const{
if(val!=t.val) return val<t.val;
return id<t.id;
}
}p[maxn];
class Splay{
private:
struct node{
int ch[2],rev,fa,sz;
node(){sz=1;}
}t[maxn];
vector<int>path;
int get(int u){return t[t[u].fa].ch[1]==u;}
void push_up(int u){t[u].sz=t[t[u].ch[0]].sz+t[t[u].ch[1]].sz+1;}
void reverse(int u){t[u].rev^=1,swap(t[u].ch[0],t[u].ch[1]);}
void down(int u){
if(!t[u].rev) return ;
if(t[u].ch[0]) reverse(t[u].ch[0]);
if(t[u].ch[1]) reverse(t[u].ch[1]);
t[u].rev=0;
}
void rotate(int u){
int fa=t[u].fa,faa=t[fa].fa;
int d=get(u),dd=get(fa);
if(faa) t[faa].ch[dd]=u;t[u].fa=faa;
t[fa].ch[d]=t[u].ch[!d];if(t[u].ch[!d]) t[t[u].ch[!d]].fa=fa;
t[u].ch[!d]=fa,t[fa].fa=u;
push_up(fa),push_up(u);
}
void splay(int u,int mb=0){
int uu=u;
while(uu!=mb) path.push_back(uu),uu=t[uu].fa;
path.push_back(uu);
while(!path.empty()) down(path.back()),path.pop_back();
for(;t[u].fa!=mb;rotate(u)) if(t[t[u].fa].fa!=mb) rotate(get(u)==get(t[u].fa)?t[u].fa:u);
}
int get_rank(int u){splay(u);return t[t[u].ch[0]].sz;}
int kth(int u,int k){
while(u){
down(u);
if(t[t[u].ch[0]].sz>=k) u=t[u].ch[0];
else if(t[t[u].ch[0]].sz+1==k) return u;
else k-=t[t[u].ch[0]].sz+1,u=t[u].ch[1];
}
return -1;
}
public:
void init(){
t[0].sz=0;
for(int i=1;i<=n;i++) read(p[i].val),p[i].id=i;
sort(p+1,p+1+n);
for(int i=1;i<=n;i++) wz[i]=p[i].id+1;
for(int i=2;i<=n+1;i++){
t[i].fa=i-1;
t[i-1].ch[1]=i;
}
t[n+2].fa=n+1,t[n+1].ch[1]=n+2;
for(int i=n+2;i>=1;i--) push_up(i);
}
void work(){
for(int i=1;i<=n;i++){
int ans;
write(ans=get_rank(wz[i])),write(" ");
int L=kth(wz[i],i),R=kth(wz[i],ans+2);
splay(L),splay(R,L);
reverse(t[R].ch[0]);
}
}
}t;
signed main(){
read(n);
t.init();
t.work();
return 0;
}

浙公网安备 33010602011771号