Hash_bzoj1862: [Zjoi2006]GameZ游戏排名系统

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 using namespace std;
  7 #define maxn 400005
  8 #define p1 63
  9 #define p2 103
 10 #define mod1 1000007
 11 #define mod2 2000007
 12 int n,tot,len,need,fact,fa[maxn],son[maxn][2],val[maxn],size[maxn];
 13 char Name[maxn][20],name[20];
 14 void read(int &x){
 15     x=0; int f=1; char ch;
 16     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') f=-1;
 17     for (;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; x*=f;
 18 }
 19 struct S{
 20     int root;
 21     void prepare(){root=0,memset(son,0,sizeof(son));}
 22     int which(int x){
 23         return son[fa[x]][1]==x;
 24     }
 25     void updata(int x){
 26         size[x]=1;
 27         if (son[x][0]) size[x]+=size[son[x][0]];
 28         if (son[x][1]) size[x]+=size[son[x][1]];
 29     }
 30     void rotata(int x){
 31         int y=fa[x],d=which(x),dd=which(y);
 32         if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y];
 33         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
 34         fa[y]=x,son[x][d^1]=y,updata(y);
 35     }
 36     void splay(int x,int goal){
 37         while (fa[x]!=goal){
 38             if (fa[fa[x]]==goal) rotata(x);
 39             else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
 40             else rotata(x),rotata(x);
 41         }
 42         updata(x); if (goal==0) root=x;
 43     }
 44     void insert(int x){
 45         int y=root; bool bo;
 46         if (root==0){
 47             root=x; updata(x);
 48             return;
 49         }
 50         for (;;){
 51             bo=0;
 52             if (val[x]<=val[y]){
 53                 if (!son[y][0]) son[y][0]=x,fa[x]=y,updata(x),updata(y),bo=1,splay(x,0);
 54                 else y=son[y][0];
 55             }else{
 56                 if (son[y][1]==0) son[y][1]=x,fa[x]=y,updata(x),updata(y),bo=1,splay(x,0);
 57                 else y=son[y][1];
 58             }
 59             if (bo==1) break;
 60         }
 61     }
 62     int prep(int x){
 63         splay(x,0);
 64         int y=son[x][0];
 65         while (son[y][1]) y=son[y][1];
 66         return y;
 67     }
 68     void Delete(int x){
 69         int y=prep(x),z;
 70         if (y==0){
 71             splay(x,0); z=son[x][1];
 72             root=z,son[x][0]=son[x][1]=fa[x]=size[x]=fa[z]=0;
 73         }else{
 74             splay(y,0),splay(x,y); z=son[x][1];
 75             fa[z]=y,son[y][1]=z,updata(y);
 76             fa[x]=son[x][0]=son[x][1]=size[x]=0;
 77         }
 78     }
 79     int rank(int x){
 80         splay(x,0);
 81         return size[son[x][0]]+1;
 82     }
 83     int kth(int x){
 84         int y=root; bool bo;
 85         for (;;){
 86             if (size[son[y][0]]+1==x) return y;
 87             else if (size[son[y][0]]>=x) y=son[y][0];
 88             else x-=size[son[y][0]]+1,y=son[y][1];
 89         }
 90     }
 91     void print(int x){
 92         if (son[x][1]) print(son[x][1]);
 93         fact++;
 94         for (int i=1;i<=Name[x][0];i++) printf("%c",Name[x][i]);
 95         if (fact<need) printf(" ");
 96         if (son[x][0]) print(son[x][0]);
 97     }
 98     void query(int u,int v){
 99         int x=kth(u-1),y=kth(v+1),z; fact=0;
100         splay(x,0),splay(y,x); z=son[y][0];
101         print(z); puts("");
102     }
103 }Splay;
104 struct hash{
105     int now[mod1+1],prep[maxn],Ha[maxn][2];
106     int ha1(){
107         int x=0;
108         for (int i=1;i<len;i++){
109             x=(x+(int)name[i])%mod1*p1%mod1;
110         }
111         return x;
112     }
113     int ha2(){
114         int x=0;
115         for (int i=1;i<len;i++){
116             x=(x+(int)name[i])%mod2*p2%mod2;
117         }
118         return x;
119     }
120     bool exist(){
121         int x1=ha1(),x2=ha2(); bool bo=0;
122         for (int i=now[x1];i;i=prep[i]){
123             if (Ha[i][0]==x2){
124                 bo=1; break;
125             }
126         }
127         return bo;
128     }
129     int number(){
130         int x1=ha1(),x2=ha2();
131         for (int i=now[x1];i;i=prep[i]){
132             if (Ha[i][0]==x2) return Ha[i][1];
133         }
134     }
135     void insert(){
136         int x1=ha1(),x2=ha2();
137         prep[++tot]=now[x1],now[x1]=tot;
138         Ha[tot][0]=x2,Ha[tot][1]=tot;
139         for (int i=1;i<len;i++) Name[tot][0]++,Name[tot][Name[tot][0]]=name[i];
140     }
141 }Hash;
142 int main(){
143     char op[20];
144     memset(size,0,sizeof(size));
145     read(n),tot=0; Splay.prepare();
146     val[n+1]=-1,val[n+2]=2147483647;
147     Splay.insert(n+1),Splay.insert(n+2);
148     for (int w,u,i=1;i<=n;i++){
149         scanf("%s",op+1);
150         if (op[1]=='+'){
151             len=strlen(op+1); read(w);
152             for (int j=2;j<=len;j++) name[j-1]=op[j];
153             if (!Hash.exist()) Hash.insert(),u=Hash.number(),val[u]=w,Splay.insert(u);
154             else{
155                 u=Hash.number();
156                 Splay.Delete(u),val[u]=w,Splay.insert(u);
157             }
158         }else if (op[1]=='?'&&!isdigit(op[2])){
159             len=strlen(op+1);
160             for (int j=2;j<=len;j++) name[j-1]=op[j];
161             w=Hash.number();
162             printf("%d\n",tot-Splay.rank(w)+2);
163         }else{
164             len=strlen(op+1); w=0;
165             for (int j=2;j<=len;j++) w=w*10+op[j]-'0';
166             w=tot-w+1;
167             u=max(1,w-10+1); need=w-u+1;
168             Splay.query(u+1,w+1);
169         }
170     }
171     return 0;
172 }
View Code

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862

题意参照题面。

做法:Splay+Hash。

裸的splay,支持插入删除查询排名即可,为什么要用Hash呢,因为如果某玩家上传过记录就得把之前的记录清空,所以我们需要用字符串Hash来判重,字符串我们使用双hash值,一个用来确定地址,第一个来作为val,这样就能降低在哈希表中查找的复杂度,再记录该玩家在Splay树中的标号即可。

splay+Hash。

posted @ 2016-07-02 14:39  oyzx~  阅读(180)  评论(0编辑  收藏  举报