zoukankan      html  css  js  c++  java
  • 洛谷P4291 [HAOI2008]排名系统 平衡树Splay

    P4291 [HAOI2008]排名系统

    题目链接

    题意

    给一个排名系统,三种操作:

    • (+name~score),名为(name)的玩家上传了新的分数(score),他之前的分数会被删除。
    • (?name),询问名为(name)的玩家的排名,得分相同的玩家,则先得到该得分的玩家排在前面。
    • (?index),询问从排名第(index)名开始的最多(10)名玩家的名字。

    分析

    将平衡树上结点维护的权值改为一个权值对((score,time)),分别表示上传的分数和时间,(score)为第一关键字,(time)为第二关键字建树就可以了,操作就全是模板操作了。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<sstream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<bitset>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb emplace_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=3e5+10;
    const int inf=1e9;
    int n,m;
    int rt,tot,ch[N][2],sz[N],fa[N],cnt[N];
    pii val[N];
    int num;
    map<string,int>g;
    int pc[N];
    string t[N];
    struct Splay{
        void maintain(int x){
            sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
        }
        bool get(int x){
            return x==ch[fa[x]][1];
        }
        void clear(int x){
            ch[x][0]=ch[x][1]=fa[x]=sz[x]=cnt[x]=0;
            val[x].fi=val[x].se=0;
        }
        void rotate(int x){
            int y=fa[x],z=fa[y],chk=get(x);
            ch[y][chk]=ch[x][chk^1];
            fa[ch[x][chk^1]]=y;
            ch[x][chk^1]=y;
            fa[y]=x;
            fa[x]=z;
            if(z) ch[z][ y==ch[z][1] ]=x;
            maintain(y);
            maintain(x);
        }
        void splay(int x,int goal=0){
            for(int f;(f=fa[x])!=goal;rotate(x)){
                if(fa[f]!=goal) rotate(get(x)==get(f)?f:x);
            }
            if(goal==0) rt=x;
        }
        void ins(pii k){
            if(!rt){
                val[++tot]=k;
                cnt[tot]++;
                rt=tot;
                maintain(rt);
                return;
            }
            int cnr=rt,f=0;
            while(1){
                if(val[cnr]==k){
                    cnt[cnr]++;
                    maintain(cnr);
                    maintain(f);
                    splay(cnr);
                    break;
                }
                f=cnr;
                cnr=ch[cnr][val[cnr]<k];
                if(!cnr){
                    val[++tot]=k;
                    cnt[tot]++;
                    fa[tot]=f;
                    ch[f][val[f]<k]=tot;
                    maintain(tot);
                    maintain(f);
                    splay(tot);
                    break;
                }
            }
        }
        int rk(pii k){
            int res=0,cnr=rt;
            while(1){
                if(k>val[cnr]){
                    cnr=ch[cnr][1];
                }else{
                    res+=sz[ch[cnr][1]];
                    if(k==val[cnr]){
                        splay(cnr);
                        return res+1;
                    }
                    res+=cnt[cnr];
                    cnr=ch[cnr][0];
                }
            }
        }
        int kth(int k){
            int cnr=rt;
            while(1){
                if(ch[cnr][1]&&sz[ch[cnr][1]]>=k){
                    cnr=ch[cnr][1];
                }else{
                    k-=cnt[cnr]+sz[ch[cnr][1]];
                    if(k<=0){
                        splay(cnr);
                        return cnr;
                    }
                    cnr=ch[cnr][0];
                }
            }
        }
        int pre(){
            int cnr=ch[rt][0];
            while(ch[cnr][1]) cnr=ch[cnr][1];
            splay(cnr);
            return cnr;
        }
        void del(pii k){
            rk(k);
            if(cnt[rt]>1){
                cnt[rt]--;
                maintain(rt);
                return;
            }
            if(!ch[rt][0]&&!ch[rt][1]){
                clear(rt);
                rt=0;
                return;
            }
            if(!ch[rt][0]){
                int cnr=rt;
                rt=ch[rt][1];
                fa[rt]=0;
                clear(cnr);
                return;
            }
            if(!ch[rt][1]){
                int cnr=rt;
                rt=ch[rt][0];
                fa[rt]=0;
                clear(cnr);
                return;
            }
            int cnr=rt,x=pre();
            splay(x);
            fa[ch[cnr][1]]=x;
            ch[x][1]=ch[cnr][1];
            clear(cnr);
            maintain(rt);
        }
    }S;
    int main(){
        ios::sync_with_stdio(false);
        //freopen("in","r",stdin);
        cin>>n;
        rep(i,1,n){
            string s;
            int k;
            cin>>s;
            if(s[0]=='+'){
                s.erase(s.begin());
                cin>>k;
                if(g[s]) S.del(mp(pc[g[s]],g[s]));
                t[n-i+1]=s;
                g[s]=n-i+1;
                pc[n-i+1]=k;
                S.ins(mp(k,n-i+1));
            }else if(s[0]=='?'&&s[1]>='A'&&s[1]<='Z'){
                s.erase(s.begin());
                cout<<S.rk(mp(pc[g[s]],g[s]))<<'
    ';
            }else{
                s.erase(s.begin());
                int k=0;
                for(char c:s) k=k*10+c-'0';
                for(int i=0;i<10&&sz[rt]>=k+i;i++){
                    S.kth(k+i);
                    cout<<t[val[rt].se]<<' ';
                }
                cout<<'
    ';
            }
        }
        return 0;
    }
    
  • 相关阅读:
    矩形覆盖
    跳台阶与变态跳台阶
    有几个PAT【*】
    找零钱
    有理数的四则运算
    旧键盘打字
    查验身份证
    完美数列【置顶】
    旧键盘
    超简单webservice实例
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13512530.html
Copyright © 2011-2022 走看看