排序机械臂
题意是:写一个数据结构,支持区间翻转,支持查找元素位次,支持删除。这就是平衡树的板子嘛,而且甚至没有插入操作。这就好办啦,我写的是splay,最近重拾平衡树代码也打得愈发顺手了……
鉴于昨天打维护序列打崩溃,总结一下关于区间翻转的几个重要的点。一个是在调用任何节点时(特别是find)一定要先一路pushdown下来,不然查找的值肯定是错误的;即使是查找元素位次的操作也是需要先pre一下,把根到自己的一路全部pushdown了之后才能安安心心查询。delete函数在把x旋转下去的时候也是需要pushdown的。
其它没什么。要对当前元素是否是最后一个特殊处理,否则可能找不到相邻元素然后死掉。
写得挺顺。记了个时38分钟,一节课吧。
code
//begin at 20:10
#include<bits/stdc++.h>
//#define zczc
const int N=100010;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline void swap(int &s1,int &s2){
int s3=s1;s1=s2;s2=s3;return;
}
int m,aa[N];
struct point{
int data,pl;
}a[N];
inline bool cmp(point s1,point s2){
return s1.data==s2.data?s1.pl<s2.pl:s1.data<s2.data;
}
#define lc t[x].ch[0]
#define rc t[x].ch[1]
struct node{
int f,ch[2],size;
bool lazy;
}t[N];
int root;
inline void pushup(int x){
if(x==0)printf("error\n");
t[x].size=t[lc].size+t[rc].size+1;
}
inline void pushnow(int x){
t[x].lazy=t[x].lazy^1;
swap(lc,rc);
}
inline void pushdown(int x){
if(t[x].lazy){
t[x].lazy=false;
pushnow(lc);pushnow(rc);
}
}
int build(int l,int r,int fa){
if(l>r)return 0;
if(l==r)return t[l].size=1,t[l].f=fa,l;
int x=l+r+1>>1;t[x].f=fa;
lc=build(l,x-1,x);rc=build(x+1,r,x);
pushup(x);return x;
}
inline int work(int x,int from){
return (from==rc?t[lc].size+1:0)+(t[x].f?work(t[x].f,x):0);
}
inline int find(int x,int kk){
pushdown(x);
if(t[lc].size>=kk)return find(lc,kk);
if(t[lc].size+1==kk)return x;
return find(rc,kk-t[lc].size-1);
}
inline void rotate(int x){
int y=t[x].f;int z=t[y].f;
int kk=t[y].ch[1]==x;int cd=t[x].ch[kk^1];
if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].f=z;
t[cd].f=y;t[y].ch[kk]=cd;
t[x].ch[kk^1]=y;t[y].f=x;
if(y==root)root=x;
pushup(y);pushup(x);return;
}
inline void splay(int x,int rt){
while(t[x].f^rt){
int y=t[x].f;int z=t[y].f;
if(z^rt)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
rotate(x);
}
if(rt==0)root=x;
}
void pre(int x){
if(t[x].f)pre(t[x].f);
pushdown(x);
}
void delete_(int x){
while(lc!=0||rc!=0){
pushdown(x);
if(lc&&rc)t[lc].size<t[rc].size?rotate(rc):rotate(lc);
else if(lc)rotate(lc);
else rotate(rc);
}
int fa=t[x].f;t[fa].ch[t[fa].ch[1]==x]=0;x=fa;
while(x)pushup(x),x=t[x].f;
return;
}
void print(int x){
if(!x)return;
pushdown(x);
printf("%d %d %d&%d %d\n",x,t[x].size,lc,rc,t[x].f);
print(lc);print(rc);
}
#undef lc
#undef rc
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
srand(time(0));
read(m);
for(int i=1;i<=m;i++){
read(a[i].data);a[i].pl=i;
aa[i]=a[i].data;
}
sort(a+1,a+m+1,cmp);
root=build(1,m,root);
//print(root);printf("\n");
for(int i=1;i<=m;i++){
int x=a[i].pl,rk;pre(x);
printf("%d ",(rk=work(x,t[x].ch[1]))+i-1);
//rk=work(x,t[x].ch[1]);
if(rk==t[root].size){
splay(x,0);pushnow(x);
}
else{
int y=find(root,rk+1);
//printf("x=%d y=%d\n",x,y);
splay(y,0);splay(x,y);
pushnow(x);
}
delete_(x);
//print(root);printf("\n");
}
return 0;
}
//finish at 20:48
一如既往,万事胜意