首页 > 代码库 > BZOJ 3506 CQOI 2014 排序机械臂 Splay

BZOJ 3506 CQOI 2014 排序机械臂 Splay

题目大意:给出一个序列,给出一种排序方式,模拟这种排序方式排序,并输出每次找到的节点的位置。


思路:它让你做什么你就做什么,无非就是个Reverse,很简单。注意一下排序的时候权值相等的情况就行了。


CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define INF 0x3f3f3f3f
using namespace std;
 
struct SplayTree{
    SplayTree *son[2],*father;
    bool reverse;
    int size;
     
    SplayTree();
    bool Check() {
        return father->son[1] == this;
    }
    void Combine(SplayTree *a,bool dir) {
        a->father = this;
        son[dir] = a;
    }
    void Reverse() {
        reverse ^= 1;
        swap(son[0],son[1]);
    }
    void PushUp() {
        size = son[0]->size + son[1]->size + 1;
    }
    void PushDown() {
        if(reverse) {
            son[0]->Reverse();
            son[1]->Reverse();
            reverse = false;
        }
    }
}none,*nil = &none,*root;
SplayTree:: SplayTree() {
    son[0] = son[1] = nil;
    reverse = false;
    size = 1;
}
 
struct Complex{
    int val,pos;
    SplayTree *a;
     
    bool operator <(const Complex &a)const {
        if(val == a.val)    return pos < a.pos;
        return val < a.val;
    }
    void Read(int p) {
        scanf("%d",&val);
        pos = p;
    }
}src[MAX];
 
int cnt;
 
void Pretreatment()
{
    nil->size = 0;
    nil->son[0] = nil->son[1] = nil->father = nil;
}
 
SplayTree *BuildTree(int l,int r)
{
    if(l > r)    return nil;
    int mid = (l + r) >> 1;
    SplayTree *re = new SplayTree();
    src[mid].a = re;
    re->Combine(BuildTree(l,mid - 1),false);
    re->Combine(BuildTree(mid + 1,r),true);
    re->PushUp();
    return re;  
}
 
inline void Rotate(SplayTree *a,bool dir)
{
    SplayTree *f = a->father;
    f->PushDown(); a->PushDown();
    f->son[!dir] = a->son[dir];
    f->son[!dir]->father = f;
    a->son[dir] = f;
    a->father = f->father;
    f->father->son[f->Check()] = a;
    f->father = a;
    f->PushUp();
    if(f == root)   root = a;
}
 
inline void Splay(SplayTree *a,SplayTree *aim)
{
    while(a->father != aim) {
        if(a->father->father == aim)
            Rotate(a,!a->Check());
        else if(!a->father->Check()) {
            if(!a->Check())
                Rotate(a->father,true),Rotate(a,true);
            else    Rotate(a,false),Rotate(a,true);
        }
        else {
            if(a->Check())
                Rotate(a->father,false),Rotate(a,false);
            else    Rotate(a,true),Rotate(a,false);
        }
    }
    a->PushUp();
}
 
SplayTree *Find(SplayTree *a,int k)
{
    a->PushDown();
    if(a->son[0]->size >= k)   return Find(a->son[0],k);
    k -= a->son[0]->size;
    if(k == 1)  return a;
    return Find(a->son[1],k - 1);
}
 
inline void SplaySeg(int x,int y)
{
    x++,y++;
    Splay(Find(root,x - 1),nil);
    Splay(Find(root,y + 1),root);
}
 
int main()
{
    cin >> cnt;
    Pretreatment();
    for(int i = 1; i <= cnt; ++i)
        src[i].Read(i); 
    src[0].val = src[cnt + 1].val = INF;
    root = BuildTree(0,cnt + 1);
    root->father = nil;
    sort(src + 1,src + cnt + 1);
    for(int i = 1; i <= cnt; ++i) {
        Splay(src[i].a,nil);
        printf("%d%c",root->son[0]->size," \n"[i == cnt]);
        SplaySeg(i,root->son[0]->size);
        root->son[1]->son[0]->Reverse();
    }
    return 0;
}


BZOJ 3506 CQOI 2014 排序机械臂 Splay