• 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);
        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
    ",name[res[sp]]);
                }
                else {
                    int t=hash(s);
                    while(1) {
                        if(!strcmp(s,name[h[t]])) {
                            printf("%d
    ",splay.rank(h[t]));
                            break;
                        }
                        else {t++; if(t==(mod+1)) t=1;}
                    }
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    线程池的使用和实现
    VS2015中搭建lua环境
    word2vect实战
    微服务架构下的数据一致性:可靠事件模式
    微服务架构下的数据一致性:概念及相关模式
    深入研究Clang(七) Clang Lexer代码阅读笔记之Lexer
    [洛谷 P1402] 酒店之王|网络流
    [BZOJ2007] [NOI2010] 海拔|网络流80‘|最短路100’
    [JSOI2008] [洛谷P1198] 最大数|线段树80'|单调栈100'
    [JSOI2008] [洛谷P1227] 完美的对称|乱搞
  • 原文地址:https://www.cnblogs.com/invoid/p/5541614.html
Copyright © 2020-2023  润新知