zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
  • 相关阅读:
    Happy Number
    [leedcode]Remove Linked List Elements
    [leedcode] Count Primes
    编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
    最短路(队列优化)
    两函数的交点
    最小生成树
    最小生成树
    线段树区间修改和查询和单点查询(线段树模板1)
    博弈论合集(博弈)
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj1862.html
Copyright © 2011-2022 走看看