P1168 中位数

splay水题。。。

本来我一看上去是懵的。脑(fan)洞(le)大(ti)开(jie)发现可以用splay来做。

构造一颗按大小排序的splay,每当弄进奇数个的时候就求一下第k大就行了。

只不过这些东西是可重的,要写一个cnt,别的没了。

代码:

#include<cstdio>

const int maxn = 100005;

int size[maxn], ch[maxn][2], fa[maxn], val[maxn], cnt[maxn];
int tot;
int n;
struct Splay
{
    int root;
    int dir(int x)
    {
        return ch[fa[x]][1] == x;
    }
    void connect(int son, int f, int k)
    {
        fa[son] = f;
        ch[f][k] = son;
    }
    void pushup(int x)
    {
        size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x];
    }
    void rotate(int x)
    {
        int y = fa[x];
        int z = fa[y];
        int yk = dir(x);
        int zk = dir(y);
        int b = ch[x][yk ^ 1];
        connect(b, y, yk);
        connect(y, x, yk ^ 1);
        connect(x, z, zk);
        pushup(y);
        pushup(x);
    }
    void splay(int x, int goal)
    {
        while(fa[x] != goal)
        {
            int y = fa[x];
            int z = fa[y];
            if(z != goal) dir(x) == dir(y) ? rotate(y) : rotate(x);
            rotate(x);
        }
        if(goal == 0) root = x;
    }
    void insert(int x)
    {
        int now = root, f = 0;
        while(now && val[now] != x)
        {
            f = now; now = ch[now][x > val[now]];
        }
        if(now) cnt[now]++;
        else
        {
            now = ++tot;
            fa[now] = f; if(f) ch[f][x > val[f]] = now;
            size[now] = 1; cnt[now] = 1; val[now] = x;
        }
        splay(now, 0);
    }
    int kth(int k)
    {
        int now = root;
        while(233)
        {
            if(size[ch[now][0]] + cnt[now] < k)
            {
                k -= size[ch[now][0]] + cnt[now];
                now = ch[now][1];
            }
            else if(size[ch[now][0]] >= k) now = ch[now][0];
            else return now;
        }
    }
    int zhongweishu()
    {
        return val[kth(size[root] / 2 + 1)];
    }
} s;
int read()
{
    int ans = 0, s = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9') ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
    return s * ans;
}
int main()
{
    n = read();
    for(int i = 1; i <= n; i++)
    {
        int temp = read();
        s.insert(temp);
        if(i % 2) printf("%d\n", s.zhongweishu());
    }
    return 0;
}
posted @ 2018-10-04 17:52  Garen-Wang  阅读(155)  评论(0编辑  收藏  举报