码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-01-04 00:35:21      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:color   play   ++   平衡树   节点   top   void   efi   bsp   

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

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

还好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]排序机械臂

标签:color   play   ++   平衡树   节点   top   void   efi   bsp   

原文地址:https://www.cnblogs.com/orzzz/p/8186026.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!