【bzoj 1552】排序机械臂

传送门~

解题思路

支持区间翻转。
代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
int n;
struct ldx{
    int x,wi; 
    bool operator < (const ldx p) const{
        return x<p.x || x==p.x && wi<p.wi;
    }
}ap[100005];
struct node{
    int siz,key;
    bool rev_mark;
    node* ch[2],*fa;
    node();
    void rev();
    void pushdown();
    void maintain();
    int son(){
        if(fa->ch[0]==this) return 0;
        if(fa->ch[1]==this) return 1;
        return -1;
    }
}*null=new node(),*s[100005],*root;
node:: node(){
    siz=null ? 1 : 0;rev_mark=0;
    ch[0]=ch[1]=fa=null; 
}
void node:: rev(){
    if(this==null) return ;
    swap(ch[0],ch[1]);
    rev_mark^=1;
}
void node:: pushdown(){
    if(!rev_mark) return ;
    rev_mark^=1;
    ch[0]->rev();ch[1]->rev();
}
void node:: maintain() {siz=ch[0]->siz+ch[1]->siz+1;}
void Rotate(node* p,bool f){
    node* t=p->ch[f^1];
    p->ch[f^1]=t->ch[f];
    if(t->ch[f]!=null) t->ch[f]->fa=p;
    t->ch[f]=p;
    p->maintain();t->maintain();
    if(~p->son()) p->fa->ch[p->son()]=t;
    t->fa=p->fa;p->fa=t;
}
void To_pushdown(node* p){
    if(p!=root) To_pushdown(p->fa);
    p->pushdown();
}
void splay(node* p,bool f){
    if(!f){
        while(~p->son()){
            int dir=p->son();
            if(p->fa->son()==dir) Rotate(p->fa->fa,dir^1);
            Rotate(p->fa,dir^1);
        }
        root=p;
    }
    else {
        while(~p->son()){
            int dir=p->son();
            if(p->fa==root) return ;
            if(p->fa->fa==root) {Rotate(p->fa,dir^1);return ;}
            if(p->fa->son()==dir) Rotate(p->fa->fa,dir^1);
            Rotate(p->fa,dir^1);
        }
    }
}
node* kth(node* p,int x){
    p->pushdown();
    int sum=p->ch[0]->siz+1;
    if(sum==x) return p;
    else if(sum>x) return kth(p->ch[0],x);
    else return kth(p->ch[1],x-sum);
}
void build(node* &p,int x,int y){
    if(x>y) return ;
    int mid=x+y>>1;p=new node();p->key=ap[mid].x;
    build(p->ch[0],x,mid-1);build(p->ch[1],mid+1,y);
    if(p->ch[0]!=null) p->ch[0]->fa=p;
    if(p->ch[1]!=null) p->ch[1]->fa=p;
    p->maintain();
}
void sett(){
    null->ch[0]=null->ch[1]=null->fa=null;
    root=new node();root->ch[1]=new node();root->ch[1]->fa=root;
    build(root->ch[1]->ch[0],1,n);root->ch[1]->ch[0]->fa=root->ch[1];
    root->ch[1]->maintain();root->maintain();
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {scanf("%d",&ap[i].x);ap[i].wi=i;}
    sett();sort(ap+1,ap+n+1);
    for(int i=1;i<=n;i++) s[i]=kth(root,ap[i].wi+1);
    for(int i=1;i<=n;i++){
        To_pushdown(s[i]);splay(s[i],0);
        if(i!=n) printf("%d ",root->ch[0]->siz);
        else printf("%d",root->ch[0]->siz);
        int k1=root->ch[0]->siz,k2=i;
        if(k1==k2) continue;
        if(k1>k2) swap(k1,k2);
        node* r1=kth(root,k1);splay(r1,0);
        node* r2=kth(root,k2+2);splay(r2,1);
        root->ch[1]->ch[0]->rev();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值