bzoj1056: [HAOI2008]排名系统 && 1862: [Zjoi2006]GameZ游戏排名系统

hash 加上 平衡树(名次树)。

这道题麻烦的地方就在于输入的是一个名字,所以需要hash。

这个hash用的是向后探查避免冲突,如果用类似前向星的方式避免冲突,比较难写,容易挂掉,但也速度快些。

mod一定要取得大一些。 hash时要减去@,否则A和B的hash值会相同导致tle。

比较难写?//蒟蒻本性。。。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1000000 + 10;
const int mod = 999983;
const int INF = 2147483647;

int n,sp,p;
char s[20],name[maxn][20],op;
int res[20];
int h[maxn];
int cnt;

struct Splay {
    int l[maxn],r[maxn],f[maxn];
    int a[maxn],s[maxn];
    int root;
    
    void update(int x) {
        s[x]=s[l[x]]+s[r[x]]+1;
    }
    
    void lr(int x) {
        int y=f[x];
        r[y]=l[x];
        if(l[x]) f[l[x]]=y;
        f[x]=f[y];
        if(root==y) root=x;
        else if(l[f[y]]==y) l[f[y]]=x;
        else r[f[y]]=x;
        f[y]=x; l[x]=y;
        update(y);
        update(x);    
    }
    
    void rr(int x) {
        int y=f[x];
        l[y]=r[x];
        if(r[x]) f[r[x]]=y;
        f[x]=f[y];
        if(root==y) root=x;
        else if(l[f[y]]==y) l[f[y]]=x;
        else r[f[y]]=x;
        f[y]=x; r[x]=y;
        update(y);
        update(x);
    }
    
    void rotate(int x) {
        if(l[f[x]]==x) rr(x);
        else lr(x);
    }
    
    void splay(int x,int target=0) {
        while(f[x] != target) {
            if(f[f[x]]==target) rotate(x);
            else if((l[f[x]]==x) == (l[f[f[x]]]==f[x])) {rotate(f[x]); rotate(x);}
            else {rotate(x); rotate(x);}
        }
    }
    
    void insert(int pos,int val) {
        int x=root,y=0;
        while(x) {
            y=x;
            x=(val<=a[x]?l[x]:r[x]);
        }
        if(val<=a[y]) l[y]=pos; else r[y]=pos;
        f[pos]=y; l[pos]=r[pos]=0;
        a[pos]=val; s[pos]=1;
        splay(pos);
    }
    
    void erase(int x) {
        splay(x);
        if(!r[root]) {
            f[l[root]]=0;    
            root=l[root];
        }
        else {
            int y=r[x];
            while(l[y]) y=l[y];
            splay(y,root);
            l[y]=l[root]; f[l[root]]=y; f[y]=0;
            root=r[root];
            update(root);
        }
    }
    
    int find(int k) {
        int x=root;
        while(s[r[x]]+1!=k) {
            if(k<s[r[x]]+1) x=r[x];
            else {k-=s[r[x]]+1; x=l[x];}
        }
        return x;
    }
    
    int rank(int x) {
        splay(x);
        return s[r[x]];
    }
    
    void access(int x) {
        if(!x) return;
        access(r[x]);
        res[++sp]=x;
        access(l[x]);
    }
    
    void init() {
        r[1]=2; f[2]=1; s[1]=2; s[2]=1; root=1; cnt=2;
        a[1]=-INF; a[2]=INF;
    }    
}splay;

int hash(char* s) {
    int l=strlen(s),res=0;
    for(int i=0;i<l;i++) 
        res=(res*27+(s[i]-'@'))%mod;
    return res;
}

int main() {
    scanf("%d\n",&n);
    splay.init();
    memset(h,0,sizeof(h));
    while(n--) {
        while(op=getchar(),op!='?'&&op!='+');
        if(op=='+') {
            scanf("%s%d",s,&p);
            int t=hash(s),pos=0;
            while(1) {
                if(!h[t]) {
                    pos=t; break;    
                }
                 else if(!strcmp(name[h[t]],s)) {pos=t; break;} 
                 else {t++; if(t==(mod+1)) t=1;} 
            }
            if(!h[pos]) {
                h[pos]=++cnt;
                memcpy(name[cnt],s,strlen(s));
                splay.insert(cnt,p);
            }
            else {
                splay.erase(h[pos]);
                splay.insert(h[pos],p);
            }
        }
        else {
            scanf("%s",s);
            if(s[0]>='0' && s[0] <='9') {
                sscanf(s,"%d",&p);
                int x=p+1,y=min(p+10,splay.s[splay.root]-1);
                x=splay.find(x-1);
                y=splay.find(y+1);
                swap(x,y);
                splay.splay(x); splay.splay(y,splay.root);
                sp=0;
                splay.access(splay.l[splay.r[splay.root]]);
                for(int j=1;j<sp;j++) printf("%s ",name[res[j]]);
                printf("%s\n",name[res[sp]]);
            }
            else {
                int t=hash(s);
                while(1) {
                    if(!strcmp(s,name[h[t]])) {
                        printf("%d\n",splay.rank(h[t]));
                        break;
                    }
                    else {t++; if(t==(mod+1)) t=1;}
                }
            }
        }
    }
    return 0;
}
posted @ 2016-05-30 10:39  invoid  阅读(...)  评论(...编辑  收藏