首页 > 代码库 > bzoj1862/1056: [Zjoi2006]GameZ游戏排名系统

bzoj1862/1056: [Zjoi2006]GameZ游戏排名系统

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1862

http://www.lydsy.com/JudgeOnline/problem.php?id=1056

【题解】

写到头昏脑涨(逃

写着写着发现不仅要记录权值和哈希值还需要记录插入时间,于是强行开了两个map来映射哈希值->权值,哈希值->插入时间

好像常数很大的样子但是跑的挺快呀。。

记住无论什么操作,都要splay到根,包括询问,因为可以构造一直询问的来卡复杂度。

好像就行了。。先放这份map的吧

技术分享
# include <map>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

struct pa {
    int v; ull h;
    pa() {}
    pa(int v, ull h) : v(v), h(h) {}
    friend bool operator == (pa a, pa b) {
        return a.v == b.v && a.h == b.h;
    }
};

int total, ind = 0, tid = 0;
map<ull, int> mp, tim;

char fys[M][12];
char str[23];
ull bin[23];

struct Splay {
    int ch[M][2], sz[M], fa[M], tm[M], siz, rt;
    pa val[M];
    int re[M], rn;
    
    inline void set() {
        siz = rn = 0;
    }
    
    inline int newnode() {
        int x = rn ? re[rn--] : (++siz);
        fa[x] = ch[x][0] = ch[x][1] = 0, sz[x] = 1; tm[x] = 0;
        return x;
    }
        
    inline void up(int x) {
        if(!x) return ;
        sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]];
    }
    
    inline void rotate(int x, int &rt) {
        int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1;
        if(y == rt) rt = x;
        else ch[z][ch[z][1] == y] = x;
        fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
        ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
        up(y), up(x);
    }
    
    inline void splay(int x, int &rt) {
        while(x != rt) {
            int y = fa[x], z = fa[y];
            if(y != rt) {
                if((ch[z][0] == y)^(ch[y][0] == x)) rotate(x, rt);
                else rotate(y, rt);
            }
            rotate(x, rt);
        }
    }
    
    inline bool cmp(pa t, pa p) {
        return t.v > p.v;
    }
    
    inline void ins(pa t, int tt) {
        int x = rt, y, te;
        while(1) {
            te = cmp(t, val[x]);
            y = ch[x][te];
            if(!y) {
                y = newnode();
                val[y] = t; tm[y] = tt;
                fa[y] = x; ch[x][te] = y;
                break;
            }
            x = y;
        }
        splay(x, rt);
    }
    
    inline int find(int x, int rk) {
        if(sz[ch[x][0]] + 1 == rk) return x;
        if(sz[ch[x][0]] + 1 < rk) return find(ch[x][1], rk - sz[ch[x][0]] - 1);
        else return find(ch[x][0], rk);
    }
    
    
    inline int find(int x, pa t, int tt) {
        if(t.v == val[x].v && tt == tm[x]) return x;
        if(t.v < val[x].v || (t.v == val[x].v && tt > tm[x])) return find(ch[x][0], t, tt);
        else return find(ch[x][1], t, tt);
    }
    
    inline int gmax(int x) {
        while(ch[x][1]) x = ch[x][1];
        return x;
    }
    
    inline int gmin(int x) {
        while(ch[x][0]) x = ch[x][0];
        return x;
    }
    
    inline void del(pa t) {
        int x = find(rt, t, tim[t.h]);
        splay(x, rt);
        int pre = gmax(ch[x][0]), nxt = gmin(ch[x][1]);
        splay(pre, rt); splay(nxt, ch[pre][1]);
        ch[nxt][0] = 0, fa[x] = 0; ch[x][0] = ch[x][1] = 0; tm[x] = 0;
        re[++rn] = x;                 // reuse
    }
    
    inline void INS(pa t) {
        int tt = tim[t.h];
        if(mp.count(t.h)) {
            int tv = mp[t.h];
            del(pa(tv, t.h));
        } else ++total;
        tim[t.h] = ++tid;
        for (int i=1; str[i]; ++i) fys[tid][i-1] = str[i];
        ins(t, tim[t.h]); mp[t.h] = t.v;
    }
    
    inline int findrk(int x, pa t, int tt) {
        if(t.v == val[x].v && tt == tm[x]) return sz[ch[x][0]] + 1;
        if(t.v < val[x].v || (t.v == val[x].v && tt > tm[x])) return findrk(ch[x][0], t, tt);
        else return sz[ch[x][0]] + 1 + findrk(ch[x][1], t, tt);
    }
        
    inline int RANK(ull h) {
        pa t = pa(mp[h], h); int tt = tim[h];
        int ret = findrk(rt, t, tt);
        int p = find(rt, t, tt); splay(p, rt); 
        return total - ret;
    }
    
    bool fir;
    inline void prt(int x) {
        if(!x) return;
        prt(ch[x][1]);
        if(fir) fir = 0;
        else printf(" ");
//        cout << val[x].h << endl;
        printf("%s", fys[tm[x]]);
        prt(ch[x][0]);
    }
    
    inline int PRT(int rk) {
        int ed = total - rk;
        rk = total - rk - min(10, total - 1 - rk) + 1;// cout << "rk = " << rk << endl;
//        debug(rt);
        int x = find(rt, rk - 1), y = find(rt, ed + 1);// cout << x << ‘ ‘ << y << endl;
        splay(x, rt); splay(y, ch[x][1]);
        fir = 1; prt(ch[y][0]); puts("");
    }
    
    inline void debug(int x) {
        if(!x) return ;
        debug(ch[x][0]);
        cout << "x = " << x << ", fa = " << fa[x] << ", ls = " << ch[x][0] << ", rs = " << ch[x][1] << ", val = {" << val[x].v << ", " << val[x].h << "}, sz = " << sz[x] << ", tm = " << tm[x] << endl;
        debug(ch[x][1]);
    }
    
}T;


inline ull ghash(char *t) {
    ull ret = 0;
    for (int i=0; t[i]; ++i) 
        ret = ret + (t[i] - A + 1) * bin[i];
    return ret;
}

inline int toint(char *t) {
    int ret = 0;
    for (int i=0; t[i]; ++i)
        ret = ret * 10 + t[i] - 0;
    return ret;
}

int main() {
    bin[0] = 1;
    for (int i=1; i<=20; ++i) bin[i] = bin[i-1] * 20000713;
    int Q, v; cin >> Q;
    T.set(); total = 2;
    // insert v
    T.siz = 2; T.rt = 1;
    T.ch[1][0] = T.ch[2][1] = T.ch[2][0] = 0; T.fa[1] = 0;
    T.val[1] = pa(-2147483648, 233), T.val[2] = pa(2147483647, 233);
    T.ch[1][1] = 2; T.fa[2] = 1; T.sz[1] = 2, T.sz[2] = 1;
    while(Q--) {
        scanf("%s", &str);
        if(str[0] == +) {
            scanf("%d", &v);
            ull ha = ghash(str+1);
            T.INS(pa(v, ha));
        } else {
            if(isdigit(str[1])) T.PRT(toint(str+1));
            else printf("%d\n", T.RANK(ghash(str+1)));
        }
    }
    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 
*/
View Code

upd: 写了个哈希表,本地跑得贼快

技术分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 2.5e5 + 10, N = 2.5e5 + 10;
const int mod = 985003;

struct pa {
    int v, h;
    pa() {}
    pa(int v, int h) : v(v), h(h) {}
    friend bool operator == (pa a, pa b) {
        return a.v == b.v && a.h == b.h;
    }
};

int total, tid = 0;

char str[23];

int head[mod + 5], nxt[N], to[N], w[N], tot = 0;
char tch[N][12];
inline void add(int u, int v, int tw, char *str) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    for (int i=0; str[i]; ++i) tch[tot][i] = str[i];
    w[tot] = tw;
}

struct Splay {
    int ch[M][2], sz[M], fa[M], tm[M], siz, rt;
    pa val[M];
    int re[M], rn;
    
    inline void set() {
        siz = rn = 0;
    }
    
    inline int newnode() {
        int x = rn ? re[rn--] : (++siz);
        fa[x] = ch[x][0] = ch[x][1] = 0, sz[x] = 1; tm[x] = 0;
        return x;
    }
        
    inline void up(int x) {
        if(!x) return ;
        sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]];
    }
    
    inline void rotate(int x, int &rt) {
        int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1;
        if(y == rt) rt = x;
        else ch[z][ch[z][1] == y] = x;
        fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
        ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
        up(y), up(x);
    }
    
    inline void splay(int x, int &rt) {
        while(x != rt) {
            int y = fa[x], z = fa[y];
            if(y != rt) {
                if((ch[z][0] == y)^(ch[y][0] == x)) rotate(x, rt);
                else rotate(y, rt);
            }
            rotate(x, rt);
        }
    }
    
    inline bool cmp(pa t, pa p) {
        return t.v > p.v;
    }
    
    inline void ins(pa t, int tt) {
        int x = rt, y, te;
        while(1) {
            te = cmp(t, val[x]);
            y = ch[x][te];
            if(!y) {
                y = newnode();
                val[y] = t; tm[y] = tt;
                fa[y] = x; ch[x][te] = y;
                break;
            }
            x = y;
        }
        splay(x, rt);
    }
    
    inline int find(int x, int rk) {
        if(sz[ch[x][0]] + 1 == rk) return x;
        if(sz[ch[x][0]] + 1 < rk) return find(ch[x][1], rk - sz[ch[x][0]] - 1);
        else return find(ch[x][0], rk);
    }
    
    
    inline int find(int x, pa t, int tt) {
        if(t.v == val[x].v && tt == tm[x]) return x;
        if(t.v < val[x].v || (t.v == val[x].v && tt > tm[x])) return find(ch[x][0], t, tt);
        else return find(ch[x][1], t, tt);
    }
    
    inline int gmax(int x) {
        while(ch[x][1]) x = ch[x][1];
        return x;
    }
    
    inline int gmin(int x) {
        while(ch[x][0]) x = ch[x][0];
        return x;
    }
    
    inline void del(pa t, int tim) {
        int x = find(rt, t, tim);
        splay(x, rt);
        int pre = gmax(ch[x][0]), nxt = gmin(ch[x][1]);
        splay(pre, rt); splay(nxt, ch[pre][1]);
        ch[nxt][0] = 0, fa[x] = 0; ch[x][0] = ch[x][1] = 0; tm[x] = 0;
        re[++rn] = x;                 // reuse
    }
    
    inline void INS(pa t) {
        int tim = -1, tv, id = -1;
        for (int i=head[t.h]; i; i=nxt[i]) 
            if(strcmp(tch[i], str+1) == 0) {
                tim = to[i]; tv = w[i]; id = i;
                break;
            }
        if(id != -1) del(pa(tv, t.h), tim);
        else ++total;
        ++tid; tim = tid;
        if(id != -1) {
            to[id] = tim; 
            w[id] = t.v;
        } else add(t.h, tim, t.v, str+1);
        ins(t, tim);
    }
    
    inline int findrk(int x, pa t, int tt) {
        if(t.v == val[x].v && tt == tm[x]) return sz[ch[x][0]] + 1;
        if(t.v < val[x].v || (t.v == val[x].v && tt > tm[x])) return findrk(ch[x][0], t, tt);
        else return sz[ch[x][0]] + 1 + findrk(ch[x][1], t, tt);
    }
        
    inline int RANK(int h) {
        int tt, tv; 
        for (int i=head[h]; i; i=nxt[i]) 
            if(strcmp(tch[i], str+1) == 0) {
                tt = to[i]; tv = w[i];
                break;
            }
        pa t = pa(tv, h);
        int ret = findrk(rt, t, tt), x = find(rt, t, tt); splay(x, rt);
        return total - ret;
    }
    
    bool fir;
    inline void prt(int x) {
        if(!x) return;
        prt(ch[x][1]);
        if(fir) fir = 0;
        else printf(" ");
//        cout << val[x].h << endl;
        for (int i=head[val[x].h]; i; i=nxt[i]) 
            if(to[i] == tm[x]) { printf("%s", tch[i]); break; }
        prt(ch[x][0]);
    }
    
    inline int PRT(int rk) {
        int ed = total - rk;
        rk = total - rk - min(10, total - 1 - rk) + 1;// cout << "rk = " << rk << endl;
//        debug(rt);
        int x = find(rt, rk - 1), y = find(rt, ed + 1);// cout << x << ‘ ‘ << y << endl;
        splay(x, rt); splay(y, ch[x][1]);
        fir = 1; prt(ch[y][0]); puts("");
    }
    
    inline void debug(int x) {
        if(!x) return ;
        debug(ch[x][0]);
        cout << "x = " << x << ", fa = " << fa[x] << ", ls = " << ch[x][0] << ", rs = " << ch[x][1] << ", val = {" << val[x].v << ", " << val[x].h << "}, sz = " << sz[x] << ", tm = " << tm[x] << endl;
        debug(ch[x][1]);
    }
    
}T;


inline int ghash(char *t) {
    int ret = 0;
    for (int i=0; t[i]; ++i) 
        ret = 1ll * ret * 20000713 % mod + t[i] - A;
    return ret % mod;
}

inline int toint(char *t) {
    int ret = 0;
    for (int i=0; t[i]; ++i)
        ret = ret * 10 + t[i] - 0;
    return ret;
}

int main() {
//    freopen("rank7.in", "r", stdin);
//    freopen("rank7-my.out", "w", stdout);
    int Q, v; cin >> Q;
    T.set(); total = 2;
    // insert v
    T.siz = 2; T.rt = 1;
    T.ch[1][0] = T.ch[2][1] = T.ch[2][0] = 0; T.fa[1] = 0;
    T.val[1] = pa(-2147483648, 233), T.val[2] = pa(2147483647, 233);
    T.ch[1][1] = 2; T.fa[2] = 1; T.sz[1] = 2, T.sz[2] = 1;
    while(Q--) {
        scanf("%s", &str);
        if(str[0] == +) {
            scanf("%d", &v);
            T.INS(pa(v, ghash(str+1)));
        } else {
            if(isdigit(str[1])) T.PRT(toint(str+1));
            else printf("%d\n", T.RANK(ghash(str+1)));
        }
    }
    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 
*/
View Code

 

bzoj1862/1056: [Zjoi2006]GameZ游戏排名系统