[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂

Posted orzzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂相关的知识,希望对你有一定的参考价值。

非常垃圾的一道平衡树,结果被日了一天。很难受嗷嗷嗷

首先不得不说网上的题解让我这个本来就不熟悉平衡树的彩笔很难受——并不好理解。

还好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法。

题意在操作时,就是第i次把编号为i-1和编号i的后继分别提到根和根的右儿子,根的右儿子的左子树打上翻转标记。

用外部数组记录原来高度第几大的在平衡树中编号是多少。就可以直接操作了。

注意有相同的高度,离散化时直接按高度第一关键字,编号第二关键字就行了。

还有每次splay要把根到当前节点都pushdown一遍。还有先pushdown再继续操作!包括判断有没有左右儿子!

可能只有我是傻逼吧

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
inline int read(){
    int r=0,c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))
    r=r*10+c-0,c=getchar();
    return r;
}
#define ls ch[x][0]
#define rs ch[x][1]
int ch[N][2],siz[N],fa[N],rev[N],pos[N];
int rt,tot;
struct qwq{
    int v,p;
}a[N];
bool cmpv(qwq p,qwq q){
    if(p.v==q.v)return p.p<q.p;
    return p.v<q.v;
}
bool cmpp(qwq p,qwq q){
    return p.p<q.p;
}
void pp(int x){
    siz[x]=siz[ls]+siz[rs]+1;
}
void pd(int x){
    if(rev[x]){
        rev[x]=0;
        swap(ls,rs);
        rev[ls]^=1;rev[rs]^=1;
    }
}
int get(int x){
    return x==ch[fa[x]][1];
}
void rotate(int x){
    int y=fa[x],z=fa[y],px=get(x),py=get(y);
    int t=ch[x][px^1];
    ch[x][px^1]=y;fa[y]=x;
    ch[y][px]=t;fa[t]=y;
    if(z)ch[z][py]=x;fa[x]=z;
    pp(y);
}
int s[N];
void splay(int x,int lim){
    int top=0;
    for(int i=x;i;i=fa[i])s[++top]=i;
    for(int i=top;i;i--)pd(s[i]);
    int y=fa[x];
    while(y^lim){
        if(fa[y]^lim)
        rotate(get(x)==get(y)?y:x);
        rotate(x);y=fa[x];
    }
    rt=!lim?x:rt;pp(x);
}
int nxt(){
    pd(rt);int x=ch[rt][1];
    while(pd(x),ch[x][0])x=ch[x][0];
    return x;
}
int build(int l,int r){
    if(l>r)return 0;
    int mid=l+r>>1,x=++tot;
    ls=build(l,mid-1);fa[ls]=x;
    rs=build(mid+1,r);fa[rs]=x;
    pos[a[mid].v]=x;
    pp(x);return x;
}
int main(){
    int n=read();
    a[1].v=0,a[n+2].v=n+1;
    for(int i=2;i<=n+1;i++)
    a[i].v=read(),a[i].p=i;
    sort(a+2,a+n+2,cmpv);
    for(int i=2;i<=n+1;i++)
    a[i].v=i-1;
    sort(a+2,a+n+2,cmpp);
    rt=build(1,n+2);
    for(int i=1;i<=n;i++){
        int x=pos[i];splay(x,0);
        printf("%d",siz[ls]);if(i^n)printf(" ");
        x=nxt();
        int y=pos[i-1];
        splay(y,0);splay(x,rt);
        rev[ls]^=1;
    }
}

 

以上是关于[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1552: [Cerc2007]robotic sort

bzoj1552 [Cerc2007]robotic sort

[BZOJ1552][Cerc2007]robotic sort

bzoj1552 [Cerc2007]robotic sort

bzoj1552/3506[Cerc2007]robotic sort splay翻转,区间最值

[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂