HDU 1890 Robotic Sort 单点查找区间翻转 Splay裸题

来源:互联网 发布:c 高级编程第10版下载 编辑:程序博客网 时间:2024/06/04 18:49

题意:给定n长的序列

找到其中靠右的最大值 Maxval 所在的位置 x

把[Maxval, x] 翻转一下。

如此进行n次排序(若Maxval==x, 则翻转[x,x] 区间(就是类似于无效操作,但是要进行)


#include<stdio.h>#include<iostream>#include<algorithm>#include<vector>#include<set>#include<queue>using namespace std;#define L(x) tree[x].ch[0]#define R(x) tree[x].ch[1]#define Father(x) tree[x].fa#define Size(x) tree[x].size#define Val(x) tree[x].val#define Minv(x) tree[x].minv#define Filp(x) tree[x].filp#define ll int#define inf 10000000#define N 200005inline ll Mid(ll x,ll y){return (x+y)>>1;}struct node{    int ch[2], fa, size;    int val, minv, filp;}tree[N];int tot, root;struct A{    int val, pos;    bool operator<(const A& a)const{        return (val==a.val&&pos<a.pos)||(val<a.val);      }  }a[N];int n;node Newnode(int val, int fa, int size){    node E={0,0,fa,size, val, val, 0};    return E;}void push_up(int id){    Size(id) = Size(L(id))+Size(R(id))+1;        Minv(id) = min(Minv(L(id)), Minv(R(id)));    Minv(id) = min(Val(id), Minv(id));}void push_down(int id){    if(Filp(id))    {        Filp(id) = 0;        Filp(L(id))^=1;        Filp(R(id))^=1;        swap(L(id),R(id));    }}void rotate(ll id, ll kind){ //kind为0代表左旋 为1代表右旋    ll y = Father(id);    push_down(id); push_down(y);    Father(tree[id].ch[kind]) = y;    tree[y].ch[kind^1] = tree[id].ch[kind];    if(Father(y))        tree[Father(y)].ch[ R(Father(y))==y ] = id;    Father(id) = Father(y);    tree[id].ch[kind] = y;    Father(y) = id;    push_up(y);}void splay(ll id, ll goal){    push_down(id);    while(Father(id)!=goal){        if(Father( Father(id) ) == goal)            rotate(id, L(Father(id)) == id);        else        {            ll y = Father(id);            ll kind = L(Father(y)) == y;            if(tree[y].ch[kind] == id) //共线            {                rotate(id, kind^1);                rotate(id, kind);            }            else            {                rotate(y, kind);                rotate(id,kind);            }        }    }    push_up(id);    if(goal == 0)root = id;}void RotateTo(ll k, ll goal){ //把第k个节点伸展到goal下    ll id = root;    push_down(id);    while(Size(L(id))!=k){        if(Size(L(id)) > k)            id = L(id);        else {            k -= (Size(L(id))+1);            id = R(id);        }        push_down(id);    }    splay(id, goal);}void Interval(ll l, ll r){    RotateTo(l, 0);    RotateTo(r, root);}ll find_min(ll v){    ll id = root;    push_down(id);    while(Val(id)!=v){        id =( (Minv(L(id))==v)?L(id):R(id) );        push_down(id);    }    return id;}ll D[N];int build(ll l, ll r, ll fa){    if(l>r)return 0;    ll mid = Mid(l,r);    ll id = tot;    tree[tot++] = Newnode(D[mid], fa, 1);    L(id) = build(l, mid-1, id);    R(id) = build(mid+1, r, id);    push_up(id);    return id;}void init(){    tree[0] = Newnode(inf,0,0);    tot = root = 1;    tree[tot++] = Newnode(inf,0,1);    tree[tot++] = Newnode(inf,R(root),1);    R(root) = tot-1;    L(R(root)) = build(1,n,R(root));    push_up(R(root));    push_up(root);}ll getmax(ll id){//找到id这个子树下的最大值的标号    push_down(id);    while(R(id)){        id = R(id);        push_down(id);    }    return id;}void Delroot(){    if(L(root)==0){        root = R(root);        Father(root) = 0;        return;    }    int now = getmax(L(root));    splay(now, root);    int id = root;    root = now;    Father(root) = 0;    R(root) = R(id);    Father(R(id)) = root;    push_up(root);}int main(){    ll i, j, u ,v;    while(scanf("%d",&n),n){        for(i=1;i<=n;i++)scanf("%d",&a[i].val), a[i].pos = i;        sort(a+1,a+n+1);        for(i=1;i<=n;i++)D[a[i].pos] = i;        init();        for(i=1;i<=n;i++){            splay(find_min(i),0);            printf("%d", Size(L(root))+i);            Filp(L(root))^=1;                        Delroot();            i==n?puts(""):printf(" ");        }    }    return 0;}





0 0