[BZOJ1056]=[BZOJ1862]排名系统

原题地址1
原题地址2

坑点超多,不过双倍经验还是很爽的…

要按双关键字排名题目根本就没有说啊囧LZ

不敢用map然后手写hash,结果…比map还慢…证明了本蒟蒻是有多弱…

AC code:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
const int L=11;
const int N=250010;
int n,tot,cnt;

struct nod{
    int  sco,num,size,fix;
    char name[L];
    nod  *lc,*rc,*pr;

    friend bool operator<(nod x,nod y){
        if(x.sco!=y.sco) return x.sco>y.sco;
        return x.num<y.num;
    }
}pool[N],*NIL;

struct data{
    nod  *pt;
    char s[L];
};
vector<data> h[N];

struct Hash{
    nod* get(char s[]){
        int key=0,len=strlen(s);
        for(int i=0,j=1;i<len;i++,j=(j*26)%N) key=(key+(s[i]-'A')*j)%N;
        for(int i=0;i<(int)h[key].size();i++){
            if(!strcmp(s,h[key][i].s)) return h[key][i].pt;
        }
        data t;
        t.pt=&pool[tot++];strcpy(t.s,s);
        h[key].push_back(t);
        return t.pt;
    }
}H;

struct Treap{
    nod *root;

    Treap(){
        root=NIL=&pool[tot++];
    }

    void newnod(nod *&p,int sco,char name[]){
        p->sco=sco;p->size=1;p->fix=rand();strcpy(p->name,name);
        p->lc=p->rc=p->pr=NIL;
    }
    void update(nod *p){
        p->size=p->lc->size+p->rc->size+1;
    }
    nod* merge(nod *p1,nod *p2){
        if(p1==NIL) return p2;
        if(p2==NIL) return p1;
        if(p1->fix>p2->fix){
            nod *p3=merge(p1->rc,p2);
            p3->pr=p1;p1->rc=p3;
            update(p1);
            return p1;
        }
        nod *p3=merge(p1,p2->lc);
        p3->pr=p2;p2->lc=p3;
        update(p2);
        return p2;
    }
    void split(nod *p,nod *&p1,nod *&p2,int k){
        if(p==NIL){
            p1=p2=NIL;
            return ;
        }
        if(p->lc->size+1>k){
            split(p->lc,p1,p2,k);
            p->lc=p->pr=NIL;
            p2=merge(p2,p);
            update(p2);
        }
        else{
            split(p->rc,p1,p2,k-p->lc->size-1);
            p->rc=p->pr=NIL;
            p1=merge(p,p1);
            update(p1);
        }
    }
    int getrank(nod *p){
        int k=p->lc->size+1;
        while(p->pr!=NIL){
            if(p->pr->rc==p) k+=p->pr->lc->size+1;
            p=p->pr;
        }
        return k;
    }
    int getrank(nod *p,nod *x){
        if(p==NIL) return 0;
        return *x<*p?getrank(p->lc,x):getrank(p->rc,x)+p->lc->size+1;
    }
    void insert(nod *p){
        nod *p1,*p2;
        split(root,p1,p2,getrank(root,p));
        root=merge(merge(p1,p),p2);
    }
    void erase(nod *p){
        nod *p1,*p2,*p3,*p4;
        split(root,p1,p2,getrank(p)-1);
        split(p2,p3,p4,1);
        root=merge(p1,p4);
    }
    void getkth(int k){
        nod *p1,*p2,*p3,*p4;
        split(root,p1,p2,k-1);
        split(p2,p3,p4,1);
        printf("%s",p3->name);
        root=merge(merge(p1,p3),p4);
    }
}T;

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int  x;
        char c;
        char s[L];
        scanf("\n%c%s",&c,s);
        if(c=='+'){
            scanf("%d",&x);
            nod *p=H.get(s);
            if(!p->size){
                T.newnod(p,x,s);
                p->num=++cnt;
                T.insert(p);
            }
            else{
                T.erase(p);
                p->sco=x;p->num=++cnt;
                T.insert(p);
            }
        }
        else{
            if(s[0]>='0'&&s[0]<='9'){
                int k=0,len=strlen(s);
                for(int i=0;i<len;i++) k=k*10+s[i]-'0';
                for(int i=0;i<10&&k+i<=T.root->size;i++){
                    if(i) printf(" ");
                    T.getkth(k+i);
                }
                printf("\n");
            }
            else printf("%d\n",T.getrank(H.get(s)));
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值