可供复制的样例:
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
题解:
唉,我splay学得实在太差了,一道题调了一个下午……总结一下错误原因:1、add的时候没有把新节点的两个儿子变为0,这样在del的时候有可能会出问题。2、很弱智的错误,读入数字写成if(ch>=’1’&&ch<=’9’)。del和ins还不是很熟悉,rotate更是不会,还是听老师的多背背代码吧……
代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=250010;
map<string,int>h;
struct Splay{int size,son[2],f,d;LL s;string name;}tr[maxn*2];
int root,z=0;
void debug()
{
for(int i=1;i<=z;i++)
printf("%d %d %d %d %d %lld ",i,tr[i].son[0],tr[i].son[1],tr[i].f,tr[i].d,tr[i].s),cout<<tr[i].name<<endl;
// puts("\n");
system("pause");//system("cls");
}
bool cmp(Splay x,Splay y)//true:x<y
{
if(x.s!=y.s)return x.s<y.s;
return x.d>y.d;
}
void push_up(int x)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
tr[x].size=tr[lc].size+tr[rc].size+1;
}
void add(int z,LL s,int f,string str,int d)
{
tr[z].s=s;tr[z].size=1;tr[z].d=d;
tr[z].f=f;tr[z].name=str;tr[z].son[0]=tr[z].son[1]=0;
if(cmp(tr[z],tr[f]))tr[f].son[0]=z;
else tr[f].son[1]=z;
}
void rotate(int x)
{
int w,y=tr[x].f,z=tr[y].f;
if(tr[y].son[0]==x) w=1;else w=0;
if(tr[x].son[w]) tr[tr[x].son[w]].f=y;
tr[y].son[1-w]=tr[x].son[w];//儿与父
if(x) tr[x].f=z;
if(tr[z].son[0]==y) tr[z].son[0]=x;
else tr[z].son[1]=x;//我与爷(取代父亲位置)
if(y) tr[y].f=x;
tr[x].son[w]=y;//父与我
push_up(y);push_up(x);
}
void splay(int x,int rt)
{
while(tr[x].f!=rt)
{
int y=tr[x].f,z=tr[y].f;
if(z==rt)rotate(x);
else
{
if((tr[z].son[0]==y)==(tr[y].son[0]==x))
rotate(y);
else rotate(x);
rotate(x);
}
}
if(!rt)root=x;
}
int findpos(LL s,int d)
{
int now=root;
while(1)
{
// printf("%d\n",now);
int lc=tr[now].son[0],rc=tr[now].son[1];
if(s>tr[now].s)
{
if(rc)now=rc;
else break;
}
else if(s<tr[now].s)
{
if(lc)now=lc;
else break;
}
else
{
if(d>tr[now].d)
{
if(lc)now=lc;
else break;
}
else if(d<tr[now].d)
{
if(rc)now=rc;
else break;
}
}
}
return now;
}
void ins(int z,LL s,string str,int d)
{
if(root==0){add(z,s,0,str,d);root=z;return;}
int x=findpos(s,d);
add(z,s,x,str,d);
push_up(x);splay(x,0);
}
void del(int x)
{
splay(x,0);
if(!tr[x].son[0]&&!tr[x].son[1]){root=z=0;return;}
if(!tr[x].son[0]&&tr[x].son[1]){root=tr[x].son[1];tr[tr[x].son[1]].f=0;return;}
if(tr[x].son[0]&&!tr[x].son[1]){root=tr[x].son[0];tr[tr[x].son[0]].f=0;return;}
int now=tr[x].son[0];
while(tr[now].son[1])now=tr[now].son[1];
splay(now,x);root=now;tr[root].f=0;
tr[root].son[1]=tr[x].son[1];
tr[tr[x].son[1]].f=root;
push_up(root);
}
//z s f str
int findren(int rank)
{
int now=root;
while(rank)
{
int lc=tr[now].son[0],rc=tr[now].son[1];
if(rank<=tr[lc].size)now=lc;
else if(rank==tr[lc].size+1)break;
else rank-=(tr[lc].size+1),now=rc;
}
return now;
}
void split(int l,int r)//让l,r这段区间独立出来
{
// printf("%d %d %d\n",l,r+2,z);
int x=findren(l),y=findren(r+2);
splay(x,0);splay(y,x);
}
bool tf;
void print(int x)
{
if(tr[x].son[1])print(tr[x].son[1]);
if(tf)tf=false;
else printf(" ");
int L=tr[x].name.size();
for(int i=0;i<L;i++)printf("%c",tr[x].name[i]);
if(tr[x].son[0])print(tr[x].son[0]);
}
int main()
{
add(++z,(1LL<<55),0,"",0);
add(++z,-(1LL<<55),1,"",0);
root=1;
int T,D=0;
LL score;
scanf("%d",&T);
while(T--)
{
char op=getchar(),ch;
string str;
while(op!='?'&&op!='+')op=getchar();
if(op=='+')
{
D++;
while(1)
{
ch=getchar();
if(ch==' ')break;
str+=ch;
}
scanf("%lld",&score);
if(h[str]==0)h[str]=++z,ins(z,score,str,D);
else
{
del(h[str]);
ins(h[str],score,str,D);
}
}
else
{
ch=getchar();
if(ch>='0'&&ch<='9')
{
int num=ch-'0';
while(1)
{
ch=getchar();
if(!(ch>='0'&&ch<='9'))break;
num=num*10+ch-'0';
}
int l=num,r=min(l+9,z-2);
swap(l,r);
// printf("%d %d %d %d\n",l,r,z-1-l,z-1-r);
split(z-1-l,z-1-r);
tf=true;
print(tr[tr[root].son[1]].son[0]);
puts("");
}
else
{
str+=ch;
while(1)
{
ch=getchar();
if(ch=='\n')break;
str+=ch;
}
int x=h[str];
splay(x,0);
printf("%d\n",z-1-tr[tr[x].son[0]].size);
}
}
}
}