ZOJ 2112 Dynamic Rankings

ZOJ_2112

    之前用线段树套平衡树写这个题目,现在发现那样写弱爆了……再次写这个题就是为了学习“主席树”,其实也就是可持久化数据结构的思想,思想来自于这篇博客:http://seter.is-programmer.com/posts/31907.html,写法来自于那个博主的代码:http://ideone.com/2Jp5W

    由于刚刚接触“主席树”就不再额外发表言论了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXM 10010
#define MAXD 60010
#define LN 16
struct Di
{
    int id, v;
    bool operator < (const Di &t) const
    {
        return v < t.v;
    }
}di[MAXD];
struct List
{
    int x, y, k;
}list[MAXM];
int N, M, S, rank[MAXD], node;
struct SegTree
{
    int ls, rs, size;
}st[2560000]; // 尽量开大些...
namespace ST
{
    int build(int x = 0, int y = S)
    {
        int cur = ++ node, mid = x + y >> 1;
        st[cur].size = 0;
        if(x < y) st[cur].ls = build(x, mid), st[cur].rs = build(mid + 1, y);
        return cur;
    }
    int insert(int pre, int v, int d)
    {
        int t = ++ node, cur = t, x = 0, y = S;
        for(;;)
        {
            int mid = x + y >> 1;
            st[cur].size = st[pre].size + d;
            if(x == y) break;
            if(v <= mid)
            {
                st[cur].rs = st[pre].rs, st[cur].ls = ++ node;
                cur = node, pre = st[pre].ls, y = mid;
            }
            else
            {
                st[cur].ls = st[pre].ls, st[cur].rs = ++ node;
                cur = node, pre = st[pre].rs, x = mid + 1;
            }
        }
        return t;
    }
}
struct ChairTree
{
    int T[20], n;
    ChairTree() : n(0){}
    ChairTree(int x) : n(1){T[0] = x;}
    operator int() const
    {
        int i, ans = 0;
        for(i = 0; i < n; i ++) ans += st[st[T[i]].ls].size;
        return ans;
    }
    void operator += (int x)
    {
        T[n ++] = x;
    }
    int operator ^= (int C)
    {
        for(int i = 0; i < n; i ++) T[i] = C ? st[T[i]].rs : st[T[i]].ls;
        return C;
    }
};
namespace BIT
{
    int T[MAXD];
    void init()
    {
        T[1] = ST::build();
        for(int i = 2; i <= N; i ++) T[i] = T[1];
    }
    void insert(int x, int v, int d)
    {
        for(;x <= N; x += x & -x) T[x] = ST::insert(T[x], v, d);
    }
    void query(ChairTree &ct, int x)
    {
        for(; x > 0; x -= x & -x) ct += T[x];
    }
}
int A[MAXD];
void init()
{
    int i, n = 0;
    char op[5];
    scanf("%d%d", &N, &M);
    for(i = 1; i <= N; i ++) scanf("%d", &di[n].v), di[n].id = n + 1, ++ n;
    for(i = 0; i < M; i ++)
    {
        scanf("%s", op);
        if(op[0] == 'Q') scanf("%d%d%d", &list[i].x, &list[i].y, &list[i].k);
        else scanf("%d%d", &list[i].x, &di[n].v), list[i].k = -1, di[n].id = n + 1, ++ n;
    }
    std::sort(di, di + n);
    rank[di[0].id] = 0;
    for(i = 1, S = 0; i < n; i ++)
    {
        if(di[i].v != di[i - 1].v) di[++ S].v = di[i].v;
        rank[di[i].id] = S;
    }
    node = 0;
    BIT::init();
    for(A[0] = BIT::T[0], i = 1; i <= N; i ++)
        A[i] = ST::insert(A[i - 1], rank[i], 1);
}
void solve()
{
    int i, n = N, C;
    for(i = 0; i < M; i ++)
    {
        if(list[i].k == -1)
        {
            BIT::insert(list[i].x, rank[list[i].x], -1);
            BIT::insert(list[i].x, rank[list[i].x] = rank[++ n], 1);
        }
        else
        {
            int x = 0, y = S, k = list[i].k;
            ChairTree a, b, c = A[list[i].y], d = A[list[i].x - 1];
            BIT::query(a, list[i].y), BIT::query(b, list[i].x - 1);
            for(;;)
            {
                if(x == y) break;
                int mid = x + y >> 1, t = a + c - b - d;
                if(k <= t) a ^= b ^= c ^= d ^= 0, y = mid;
                else k -= t, a ^= b ^= c ^= d ^= 1, x = mid + 1;
            }
            printf("%d\n", di[x].v);
        }
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t --)
    {
        init();
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/staginner/p/2676040.html