HDU - 5096 ACM Rank (Treap)

平衡树的题,Treap破之,比较难搞的出现相同题数罚时的情况,解决方法是在每个结点用一个set,

保证结点值的时候可以把题数和罚时保存到一个int里,令v = n*MaxPenaltySum-penalty。这样就可以很方便地做比较了。

初始化有一定技巧。细节很多容易出错。 写静态版,如果有合并操作要内存池开到最大结点数量的两倍,内存多随意

写错一个变量名字查好久,尴尬

hdu似乎不资磁PB_ds这种黑科技

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

#define PB push_back
#define MP make_pair
#define fi first
#define se second

#define cer(x) cout<<#x<<'='<<endl
typedef long long ll;

const int maxn = 1e4+5, MAXPEN = 1e6;//60*20+3000+666;

int st[maxn], val[maxn], pen[maxn][10],lst[maxn],lsa[maxn];

struct CMP
{
    bool operator()(int a,int b) const{
        return lsa[a] < lsa[b];
    }
};

struct Node
{
    int ch[2],r,s,v;
    set<int,CMP> vs;
}nds[maxn*2];
queue<int> fre;

inline int newNode(int x)
{
    int i;
    Node &u = nds[i = fre.front()]; fre.pop();
    u.ch[0] = u.ch[1] = 0;
    u.r = rand(); u.s = 1; u.v = val[x];
    u.vs.clear(); u.vs.insert(x);
    return i;
}

inline void delt(int x)
{
    fre.push(x);
}

inline int cmp(int a,int b)
{
    if(a == b) return -1;
    return a>b? 0:1;
}

inline void mt(int i)
{
    Node&u = nds[i];
    u.s = (int)u.vs.size() + nds[u.ch[0]].s + nds[u.ch[1]].s;
}

inline void rot(int &o,int d)
{
    int k = nds[o].ch[d^1];
    nds[o].ch[d^1] = nds[k].ch[d];
    nds[k].ch[d] = o;
    mt(o); mt(k);
    o = k;
}

inline void initTreap(int n)
{
    for(int i = 1; i < n; i++) fre.push(i);
    nds[0].s = 0;
}

void inst(int &o,int x)
{
    if(!o) {
        o = newNode(x); return;
    }
    Node &u = nds[o];
    int d = cmp(u.v,val[x]);
    if(~d){
        inst(u.ch[d],x);
        if(u.r < nds[u.ch[d]].r) rot(o,d^1);
        //else
    }else {
        u.s++; u.vs.insert(x);
    }
    mt(o);
}

void rmov(int &o,int x)
{
    Node &u = nds[o];
    int d = cmp(u.v,val[x]);
    if(~d){
        rmov(u.ch[d],x);
    }else {
        if((int)u.vs.size() > 1){
            u.vs.erase(x); u.s--;
        }else {
            if(u.ch[0] && u.ch[1]){
                int d2 = nds[u.ch[0]].r > nds[u.ch[1]].r ? 1:0;
                rot(o,d2); rmov(nds[o].ch[d2],x);
            }else {
                delt(o);
                if(!u.ch[0]) o = u.ch[1];
                else o = u.ch[0];
            }
        }
    }
    if(o) mt(o);
}


int Rank(int o,int x)
{
    Node &u = nds[o];
    int d = cmp(u.v,val[x]);
    if(d == 1) return Rank(u.ch[1],x);
    int s = nds[u.ch[1]].s;
    if(d == 0) return s+(int)u.vs.size()+Rank(u.ch[0],x);
    return s+1;
}

int Kth(int o,int k)
{
    if(!o || k <= 0 || k > nds[o].s) return -1;//
    Node &u = nds[o];
    int s = nds[u.ch[1]].s;
    if(k == s+1) return *(u.vs.begin());
    if(k <= s) return Kth(u.ch[1],k);
    return Kth(u.ch[0],k-s-(int)u.vs.size());
}

void rmvTree(int o)
{
    if(nds[o].ch[0]) rmvTree(nds[o].ch[0]);
    if(nds[o].ch[1]) rmvTree(nds[o].ch[1]);
    delt(o);
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("data.txt","r",stdin);
#endif
    int N,M;
    char op[50];
    initTreap(maxn*2);
    int root = 0;
    while(~scanf("%d%d",&N,&M)){
        if(root) rmvTree(root);
        root = 0;
        fill(st,st+N,0);
        fill(val,val+N,0);
        fill(lst,lst+N,-5);
        memset(pen,0,sizeof(pen));
        for(int i = 0; i < N; i++){
            lsa[i] = -N+i;
            inst(root,i);
        }
        int c = 0;
        while(~scanf("%s",op)&&*op != 'C'){
            if(*op == 'S'){
                int t,x,re; char pro; scanf("%d:%d:%c:%d",&t,&x,&pro,&re);
                int p = pro-'A';
                if(t - lst[x] < 5 || (st[x]&(1<<p))) continue;
                lst[x] = t;
                if(re == 1){
                    printf("[%d][%c]\n",x,pro);
                    rmov(root,x);
                    lsa[x] = ++c;
                    st[x] |= 1<<p;
                    val[x] += MAXPEN-pen[x][p]-t;
                    inst(root,x);
                }else pen[x][p] += 20;
            }else if(*op == 'R'){
                int x; scanf("%d",&x);
                printf("%d\n",Rank(root,x));
            }else if(*op == 'T'){
                int k; scanf("%d",&k);
                printf("%d\n",Kth(root,k));
            }
        }
        scanf("%s",op);
        puts("");
    }
    return 0;
}

 

posted @ 2015-09-19 10:51  陈瑞宇  阅读(350)  评论(0编辑  收藏  举报