HDU1890 Robotic Sort

我不是code的生產者,我只是code的搬運工。(感謝cxlove世界冠軍提供參考代碼,我已經成功從中提取了模板= =)


好吧,其實這個除了上一題的模板之外完全是我自己寫的,連那個remove函數都是現編的= =

要注意的是數據可能有重複,需要處理一下。


splay中使用rotate函數,用時296MS:


#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn = 100010;
int n;
int val[maxn], fa[maxn], ch[maxn][2], size[maxn], root, tot;
int rev[maxn];

struct node
{
    int v, id;
    bool operator < (const node &o) const
    {
        return (v==o.v && id < o.id) || v < o.v;
    }
}a[maxn];

inline void init()
{
    root = tot = 0;
    val[0] = fa[0] = ch[0][0] = ch[0][1] = size[0] = 0;
    rev[0] = 0;
}

inline void newnode(int x, int value, int father)
{
    val[x] = value;
    fa[x] = father;
    ch[x][0] = ch[x][1] = 0;
    size[x] = 1;
    rev[x] = 0;
}

inline void push_down(int x)
{
    if (!rev[x]) return;
    swap(ch[x][0], ch[x][1]);
    rev[ch[x][0]] ^= 1;
    rev[ch[x][1]] ^= 1;
    rev[x] = 0;
}

inline void push_up(int x)
{
    size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
}

inline void rotate(int x, int kind)
{
    int y = fa[x];
    push_down(x); push_down(y);
    ch[y][kind^1] = ch[x][kind];
    fa[ch[x][kind]] = y;
    if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y] = x;
    fa[x] = fa[y];
    ch[x][kind] = y;
    fa[y] = x;
    push_up(y);
}

inline void splay(int x, int goal)
{
    push_down(x);
    while (fa[x] != goal)
    {
        int y = fa[x];
        if (fa[y] == goal)
        {
            push_down(y); push_down(x);
            rotate(x, ch[y][0]==x);
        }
        else
        {
            push_down(fa[y]); push_down(y); push_down(x);
            int kind = ch[fa[y]][0]==y;
            if (ch[y][kind] == x) {rotate(x, kind^1); rotate(x, kind);}
            else {rotate(y, kind); rotate(x, kind);}
        }
    }
    push_up(x);
    if (goal == 0) root = x;
}

inline void remove(int x)
{
    int y = fa[x];
    if (!ch[x][0])
    {
        ch[y][ch[y][1]==x] = ch[x][1];
        fa[ch[x][1]] = y;
    }
    else
    {
        int z = ch[x][0];
        push_down(z);
        while (ch[z][1])
        {
            z = ch[z][1];
            push_down(z);
        }
        splay(z, y);
        ch[z][1] = ch[x][1];
        fa[ch[x][1]] = z;
        ch[y][ch[y][1]==x] = z;
        fa[z] = y;
    }
}

inline void build(int &x, int l, int r, int father)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x = mid, a[mid].v, father);
    if (l < mid) build(ch[x][0], l, mid-1, x);
    if (mid < r) build(ch[x][1], mid+1, r, x);
    push_up(x);
}

int main()
{
    while (scanf("%d", &n) == 1 && n)
    {
        for (int i=1;i<=n;i++) scanf("%d", &a[i].v), a[i].id = i;
        sort(a+1, a+n+1);
        init();
        build(root, 1, n, 0);
        for (int i=1;i<n;i++)
        {
            int x = a[i].id;
            splay(x, 0);
            printf("%d ", size[ch[x][0]] + i);
            rev[ch[x][0]] ^= 1;
            remove(root);
        }
        printf("%d\n", n);
    }
    return 0;
}


splay中使用zigzag,用時281MS:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn = 100010;
int n;
int val[maxn], fa[maxn], ch[maxn][2], size[maxn], root, tot;
int rev[maxn];

struct node
{
    int v, id;
    bool operator < (const node &o) const
    {
        return (v==o.v && id < o.id) || v < o.v;
    }
}a[maxn];

inline void init()
{
    root = tot = 0;
    val[0] = fa[0] = ch[0][0] = ch[0][1] = size[0] = 0;
    rev[0] = 0;
}

inline void newnode(int x, int value, int father)
{
    val[x] = value;
    fa[x] = father;
    ch[x][0] = ch[x][1] = 0;
    size[x] = 1;
    rev[x] = 0;
}

inline void push_down(int x)
{
    if (!rev[x]) return;
    swap(ch[x][0], ch[x][1]);
    rev[ch[x][0]] ^= 1;
    rev[ch[x][1]] ^= 1;
    rev[x] = 0;
}

inline void push_up(int x)
{
    size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
}

inline void zig(int x)
{
    int y = fa[x], z = fa[y];
    ch[y][1] = ch[x][0]; fa[ch[x][0]] = y;
    ch[x][0] = y; fa[y] = x;
    fa[x] = z;
    if (z) ch[z][ch[z][1]==y] = x;
    push_up(y);
}

inline void zag(int x)
{
    int y = fa[x], z = fa[y];
    ch[y][0] = ch[x][1]; fa[ch[x][1]] = y;
    ch[x][1] = y; fa[y] = x;
    fa[x] = z;
    if (z) ch[z][ch[z][1]==y] = x;
    push_up(y);
}

inline void zigzig(int x)
{
    int y = fa[x], z = fa[y], fz = fa[z];
    ch[z][1] = ch[y][0]; fa[ch[y][0]] = z;
    ch[y][1] = ch[x][0]; fa[ch[x][0]] = y;
    fa[z] = y; ch[y][0] = z;
    fa[y] = x; ch[x][0] = y;
    fa[x] = fz;
    if (fz) ch[fz][ch[fz][1]==z] = x;
    push_up(z); push_up(y);
}

inline void zagzag(int x)
{
    int y = fa[x], z = fa[y], fz = fa[z];
    ch[z][0] = ch[y][1]; fa[ch[y][1]] = z;
    ch[y][0] = ch[x][1]; fa[ch[x][1]] = y;
    fa[z] = y; ch[y][1] = z;
    fa[y] = x; ch[x][1] = y;
    fa[x] = fz;
    if (fz) ch[fz][ch[fz][1]==z] = x;
    push_up(z); push_up(y);
}

inline void zigzag(int x)
{
    int y = fa[x], z = fa[y], fz = fa[z];
    ch[y][1] = ch[x][0]; fa[ch[x][0]] = y;
    ch[z][0] = ch[x][1]; fa[ch[x][1]] = z;
    fa[y] = fa[z] = x;
    ch[x][0] = y; ch[x][1] = z;
    fa[x] = fz;
    if (fz) ch[fz][ch[fz][1]==z] = x;
    push_up(z); push_up(y);
}

inline void zagzig(int x)
{
    int y = fa[x], z = fa[y], fz = fa[z];
    ch[y][0] = ch[x][1]; fa[ch[x][1]] = y;
    ch[z][1] = ch[x][0]; fa[ch[x][0]] = z;
    fa[y] = fa[z] = x;
    ch[x][1] = y; ch[x][0] = z;
    fa[x] = fz;
    if (fz) ch[fz][ch[fz][1]==z] = x;
    push_up(z); push_up(y);
}

void splay(int x, int goal)
{
    int y, z;
    push_down(x);
    while(fa[x] != goal)
    {
        int y = fa[x];
        if (fa[y] == goal){
            push_down(y); push_down(x);
            if (ch[y][1] == x) zig(x);
            else zag(x);
        }
        else
        {
            z = fa[y];
            push_down(z); push_down(y); push_down(x);
            if (ch[z][1] == y)
            {
                if (ch[y][1] == x) zigzig(x);
                else zagzig(x);
            }
            else
            {
                if (ch[y][0] == x) zagzag(x);
                else zigzag(x);
            }
        }
    }
    push_up(x);
    if (fa[x] == 0) root=x;
}

inline void remove(int x)
{
    int y = fa[x];
    if (!ch[x][0])
    {
        ch[y][ch[y][1]==x] = ch[x][1];
        fa[ch[x][1]] = y;
    }
    else
    {
        int z = ch[x][0];
        push_down(z);
        while (ch[z][1])
        {
            z = ch[z][1];
            push_down(z);
        }
        splay(z, y);
        ch[z][1] = ch[x][1];
        fa[ch[x][1]] = z;
        ch[y][ch[y][1]==x] = z;
        fa[z] = y;
    }
}

inline void build(int &x, int l, int r, int father)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x = mid, a[mid].v, father);
    if (l < mid) build(ch[x][0], l, mid-1, x);
    if (mid < r) build(ch[x][1], mid+1, r, x);
    push_up(x);
}

int main()
{
    while (scanf("%d", &n) == 1 && n)
    {
        for (int i=1;i<=n;i++) scanf("%d", &a[i].v), a[i].id = i;
        sort(a+1, a+n+1);
        init();
        build(root, 1, n, 0);
        for (int i=1;i<n;i++)
        {
            int x = a[i].id;
            splay(x, 0);
            printf("%d ", size[ch[x][0]] + i);
            rev[ch[x][0]] ^= 1;
            remove(root);
        }
        printf("%d\n", n);
    }
    return 0;
}


所以說,雖然提速不是太多,但是zigzag也算是一個外掛吧,關鍵時刻說不定會有用。

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