bzoj3506 [Cqoi2014]排序機械臂

splay的區間操作(區間反轉)

由於splay表示的是區間,對於重複元素的查找可能會出錯(只是splay的實現導致的,沒有辦法)

離散化那個地方有點小技巧,主要是針對數據的重複性,也就是去重。

我這裏有對這個問題的小結:http://hlq07.sinaapp.com/archives/15/

#include<bits/stdc++.h>
using namespace std;

struct node {
    int key, size, Min;
    bool sig;
    node *c[2];
    node():key(0), size(0), Min(INT_MAX)  {   c[0] = c[1] = this; }
    node(int key, node *c0, node *c1):key(key), sig(0)  {   c[0] = c0, c[1] = c1;   }
    node *rz()  {   return size = c[0]->size + c[1]->size + 1, Min = min(key, min(c[0]->Min, c[1]->Min)), this;    }
    void push_down()    {
        if(!sig)    return ;
        sig ^= 1, c[0]->sig ^= 1, c[1]->sig ^= 1;
        swap(c[0], c[1]);
    }
}   Tnull, *null = &Tnull;

struct splay    {
    node *root;
    void zig(bool d)    {
        node *t = root->c[d];
        root->c[d] = null->c[d];
        null->c[d] = root;
        root = t;
    }
    void zigzig(bool d) {
        node *t = root->c[d]->c[d];
        root->c[d]->c[d] = null->c[d];
        null->c[d] = root->c[d];
        root->c[d] = null->c[d]->c[!d];
        null->c[d]->c[!d] = root->rz();
        root = t;
    }
    void finish(bool d)   {
        node *t = null->c[d], *p = root->c[!d];
        while(t != null)    {
            t = null->c[d]->c[d];
            null->c[d]->c[d] = p;
            p = null->c[d]->rz();
            null->c[d] = t;
        }
        root->c[!d] = p;
    }
    void select(int k)   {
        int t;
        while(1)    {
            root->push_down();
            bool d = k > (t = root->c[0]->size);
            if(k == t || root->c[d] == null)    break;
            if(d)   k -= t + 1;
            root->c[d]->push_down();
            bool dd = k > (t = root->c[d]->c[0]->size);
            if(k == t || root->c[d]->c[dd] == null) {
                zig(d);
                break;
            }
            if(dd)  k -= t + 1;
            d != dd ? zig(d), zig(dd) : zigzig(d);
        }
        finish(0), finish(1);
        root->rz();
    }
    void search_min()   {
        while(1)    {
            root->push_down();
            bool d = root->Min < root->c[0]->Min;
            if(root->c[d] == null || root->Min == root->key)  break;    //適應題目需要加上 "x == root->key",刪去x > root->key的判斷
            root->c[d]->push_down();
            bool dd = root->c[d]->Min < root->c[d]->c[0]->Min;
            if(root->c[d]->c[dd] == null || root->c[d]->Min == root->c[d]->key)   {
                zig(d);
                break;
            }
            d != dd ? zig(d), zig(dd) : zigzig(d);
        }
        finish(0), finish(1);
        root->rz();
    }
    void del_min() {
        search_min();
        node *oldroot = root;
        root = oldroot->c[1];
        select(0);
        root->c[0] = oldroot->c[0];
        root->rz();
        root->c[0]->sig ^= 1;
        delete oldroot;
    }
}   sp;

node *Build(int *st, int *ed) {
    if(st == ed)    return null;
    int *mid = st + (ed - st) / 2;
    return (new node(*mid, Build(st, mid), Build(mid + 1, ed)))->rz();
}

const int MAXN = 100000;
int n, A[MAXN + 10], tmp[MAXN + 10];
int cnt[MAXN + 10];

int main()  {
    int i;
    scanf("%d", &n);
    for(i = 1; i <= n; i++) {
        scanf("%d", &A[i]);
        tmp[i] = A[i];
    }
    sort(tmp + 1, tmp + 1 + n);
    for(i = 1; i <= n; i++) {
        int t = lower_bound(tmp + 1, tmp + 1 + n, A[i]) - tmp;
        A[i] = t + cnt[t];
        cnt[t]++;
    }
    A[n + 1] = INT_MAX;
    sp.root = Build(A + 1, A + n + 2);
    for(i = 1; i <= n; i++) {
        sp.del_min();
        printf(i == n ? "%d\n" : "%d ", sp.root->c[0]->size + i);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章