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 }
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862
题意参照题面。
做法:Splay+Hash。
裸的splay,支持插入删除查询排名即可,为什么要用Hash呢,因为如果某玩家上传过记录就得把之前的记录清空,所以我们需要用字符串Hash来判重,字符串我们使用双hash值,一个用来确定地址,第一个来作为val,这样就能降低在哈希表中查找的复杂度,再记录该玩家在Splay树中的标号即可。
splay+Hash。