思路:

\(FHQ\_treap\ or\ splay\)维护得分对应的名字\(\And\)用另一个平衡树维护名字\(hash\)后对应的得分\(,\)输出时区间提取。(如果单次查询找\(10\)次排名可能会\(TLE\)

当然,为了区分得分相同但名字不同的可以使用时间戳\(or\)随机数

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
# define Type template<typename T>
# define read read1<int>()
Type inline T read1()
{
    T t=0;
    bool ty=0;
    char k;
    do k=getchar(),(k=='-')&&(ty=1);while('0'>k||k>'9');
    do t=(t<<3)+(t<<1)+(k^'0'),k=getchar();while('0'<=k&&k<='9');
    return ty?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
template<typename T>
    class FHQ_treap
    {
        private:
            int seed;
        public:
            int Rand(){return seed=seed*33457+52331314;}
            class node
            {
                public:
                    node *l,*r;
                    T k;
                    int cnt,si,q;
                    node(){l=r=NULL;cnt=si=1;}
                    node(T k1,int q1){l=r=NULL;cnt=si=1;k=k1;q=q1;}
            }*root;
            class Pair
            {
                public:
                    node *l,*r;
                    Pair(){}
                    Pair(node *a,node *b){l=a;r=b;}
            };
        private:
            void pushup(node *n){n->si=size(n->l)+size(n->r)+n->cnt;}
            int size(node *n){return n?n->si:0;}
            Pair _split(node *n,T v)
            {
                if(!n)return Pair(NULL,NULL);
                Pair tem;
                if(v<n->k)
                {
                    tem=_split(n->l,v);
                    n->l=tem.r;
                    tem.r=n;
                }
                else
                {
                    tem=_split(n->r,v);
                    n->r=tem.l;
                    tem.l=n;
                }
                pushup(n);
                return tem;
            }
            Pair split_(node *n,T v)
            {
                if(!n)return Pair(NULL,NULL);
                Pair tem;
                if(v<=n->k)
                {
                    tem=split_(n->l,v);
                    n->l=tem.r;
                    tem.r=n;
                }
                else
                {
                    tem=split_(n->r,v);
                    n->r=tem.l;
                    tem.l=n;
                }
                pushup(n);
                return tem;
            }
            node* merge(node *l,node *r)
            {
                if(!l or !r)return l?l:r;
                node* re;
                if(l->q<r->q)l->r=merge(l->r,r),re=l;
                else r->l=merge(l,r->l),re=r;
                pushup(re);
                return re;
            }
            node* findmin(node* n){while(n->l)n=n->l;return n;}
            node* findmax(node* n){while(n->r)n=n->r;return n;}
        public:
            FHQ_treap(){root=NULL;seed=4088;}
            void insert(T ke)
            {
                Pair tem=_split(root,ke),tem1=split_(tem.l,ke);
                if(tem1.r)++tem1.r->cnt,++tem1.r->si;
                else tem1.r=new node(ke,Rand());
                root=merge(merge(tem1.l,tem1.r),tem.r);
            }
            void del(T ke)
            {
                Pair tem=_split(root,ke),tem1=split_(tem.l,ke);
                if(tem1.r and --tem1.r->cnt)--tem1.r->si,tem1.l=merge(tem1.l,tem1.r);
                root=merge(tem1.l,tem.r);
            }
            T upper(T ke)
            {
                Pair tem=_split(root,ke);
                T tans=findmin(tem.r)->k;
                merge(tem.l,tem.r);
                return tans;
            }
            T lower(T ke)
            {
                Pair tem=split_(root,ke);
                T tans=findmax(tem.l)->k;
                merge(tem.l,tem.r);
                return tans;
            }
            int findrank(T ke)
            {
                Pair tem=split_(root,ke);
                int tans=size(tem.l)+1;
                merge(tem.l,tem.r);
                return tans;
            }
            T findwho(int n)
            {
                for(node* i=root;i;)
                    if(n<=size(i->l))i=i->l;
                    else if(size(i->l)+i->cnt<n)n-=size(i->l)+i->cnt,i=i->r;
                    else return i->k;
                return 0;
            }
    };
template<typename T,typename _T>
    class FHQ_treap_map
    {
        private:
            int seed,space;
        public:
            int Rand(){return seed=seed*33457+52331314;}
            class node
            {
                public:
                    node *l,*r;
                    T k;_T v;
                    int cnt,si,q;
                    node(){l=r=NULL;cnt=si=1;}
                    node(T k1,_T v1,int q1){l=r=NULL;cnt=si=1;k=k1;v=v1;q=q1;}
            }*root;
            class Pair
            {
                public:
                    node *l,*r;
                    Pair(){}
                    Pair(node *a,node *b){l=a;r=b;}
            };
        private:
            void pushup(node *n){n->si=size(n->l)+size(n->r)+n->cnt;}
            int size(node *n){return n?n->si:0;}
            Pair split(node *n,int ra)
            {
                if(!n)return Pair(NULL,NULL);
                Pair tem;
                if(ra<=size(n->l))
                {
                    tem=split(n->l,ra);
                    n->l=tem.r;
                    tem.r=n;
                }
                else
                {
                    tem=split(n->r,ra-size(n->l)-n->cnt);
                    n->r=tem.l;
                    tem.l=n;
                }
                pushup(n);
                return tem;
            }
            Pair _split(node *n,T v)
            {
                if(!n)return Pair(NULL,NULL);
                Pair tem;
                if(v<n->k)
                {
                    tem=_split(n->l,v);
                    n->l=tem.r;
                    tem.r=n;
                }
                else
                {
                    tem=_split(n->r,v);
                    n->r=tem.l;
                    tem.l=n;
                }
                pushup(n);
                return tem;
            }
            Pair split_(node *n,T v)
            {
                if(!n)return Pair(NULL,NULL);
                Pair tem;
                if(v<=n->k)
                {
                    tem=split_(n->l,v);
                    n->l=tem.r;
                    tem.r=n;
                }
                else
                {
                    tem=split_(n->r,v);
                    n->r=tem.l;
                    tem.l=n;
                }
                pushup(n);
                return tem;
            }
            node* merge(node *l,node *r)
            {
                if(!l or !r)return l?l:r;
                node* re;
                if(l->q<r->q)l->r=merge(l->r,r),re=l;
                else r->l=merge(l,r->l),re=r;
                pushup(re);
                return re;
            }
            node* findmin(node* n){while(n->l)n=n->l;return n;}
            node* findmax(node* n){while(n->r)n=n->r;return n;}
        public:
            FHQ_treap_map(){root=NULL;seed=4088;}
            void insert(T ke,_T va)
            {
                ++space;
                Pair tem=_split(root,ke);
                root=merge(merge(tem.l,new node(ke,va,Rand())),tem.r);
            }
            void del(T ke)
            {
                --space;
                Pair tem=_split(root,ke),tem1=split_(tem.l,ke);
                root=merge(tem1.l,tem.r);
            }
            T upper(T ke)
            {
                Pair tem=_split(root,ke);
                T tans=findmin(tem.r)->k;
                merge(tem.l,tem.r);
                return tans;
            }
            T lower(T ke)
            {
                Pair tem=split_(root,ke);
                T tans=findmax(tem.l)->k;
                merge(tem.l,tem.r);
                return tans;
            }
            int findrank(T ke)
            {
                Pair tem=split_(root,ke);
                int tans=size(tem.l)+1;
                merge(tem.l,tem.r);
                return tans;
            }
            T findwho(int n)
            {
                for(node* i=root;i;)
                    if(n<=size(i->l))i=i->l;
                    else if(size(i->l)+i->cnt<n)n-=size(i->l)+i->cnt,i=i->r;
                    else return i->k;
                return 0;
            }
            bool find(T n)
            {
                for(node* i=root;i;)
                    if(i->k==n)return 1;
                    else if(i->k>n)i=i->l;
                    else i=i->r;
                return 0;
            }
            _T operator [] (const T n)
            {
                for(node* i=root;i;)
                    if(i->k==n)return i->v;
                    else if(i->k>n)i=i->l;
                    else i=i->r;
                return root->v;
            }
            void pr(node* n,void (*w)(_T) )
            {
                if(!n)return;
                pr(n->l,w);
                w(n->v);putchar(' ');
                pr(n->r,w);
            }
            void query(int l,int r,void (*w)(_T) )
            {
                if(r>space)r=space;
                Pair tem=split(root,l-1),tem1=split(tem.r,r-l+1);
                pr(tem1.l,w);
                merge(tem.l,merge(tem1.l,tem1.r));
            }
    };
# define ull unsigned long long
# define A pair<int,int>
FHQ_treap_map<A,ull>tr;
char str[11];
FHQ_treap_map<ull,A>ma;
ull Hash(char* str)
{
    ull t=0;
    while(*str)t=t*27ull+*str-'A'+1,++str;
    return t;
}
void print(ull k)
{
    if(!k)return;
    print(k/27ull);
    putchar('A'+k%27ull-1);
}
int main()
{
    //fre("1");
    int D=0;
    for(int T=read;T--;)
    {
        scanf("%s",str);
        ull has,te;
        if(*str=='+')
        {
            has=Hash(str+1);
            if(ma.find(has))tr.del(ma[has]),ma.del(has);
            ma.insert(has,A(te=-read,++D));
            tr.insert(A(te,D),has);
        }
        else if(*str=='?')
            if(*(str+1)<'A')
            {
                int ke;
                sscanf(str+1,"%d",&ke);
                tr.query(ke,ke+9,print);
                putchar('\n');
            }
            else if(ma.find(has=Hash(str+1)))
                    printf("%d\n",tr.findrank(ma[has]));
    }
    return 0;
}
/*
20
+ADAM 1000000
+BOB 1000000
+TOM 2000000
+CATHY 10000000
?TOM
?1
+DAM 100000
+BOB 1200000
+ADAM 900000
+FRANK 12340000
+LEO 9000000
+KAINE 9000000
+GRACE 8000000
+WALT 9000000
+SANDY 8000000
+MICK 9000000
+JACK 7320000
?2
?5
?KAINE

*/
01-11 14:46