要求打一个数据结构,支持单点修改,单点排名查询,区间排名查询。
Splay模板题。
可以多加两个节点在两边,开个数组记录玩家在Splay上的位置。
然而bzoj卡cin,又懒,不想打哈希,于是愉快的精神AC了。
可以交codevs:http://codevs.cn/problem/1985/
手贱错误:
del操作while(tr[p].son[1]!=0) p=tr[p].son[1]; 不要手贱成while(tr[p].son[1]!=0) p=tr[x].son[1];
ins操作后要更新x节点
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<map>
#include<string>
#include<iostream>
#define LL long long
using namespace std;
const LL inf=(1LL<<55);
const int maxn=1320020;
struct trnode{
int d2,id,c,son[2],fa;//d1是权值 d2是位置权
LL d1;
}tr[maxn];int root=0,len=0,n;
map <string ,int> name;
struct node{
string s;
int id,len;
}a[maxn];int num=0,tot=0;
void update(int x)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
tr[x].c=tr[lc].c+tr[rc].c+1;
}
bool big(LL x1,int x2,LL y1,int y2)
{
if(x1>y1) return true;
if(x1<y1) return false;
return x2<y2;
}
void add(LL d1,int d2,int fa,int id,int x)
{
tr[x].d1=d1;tr[x].d2=d2;tr[x].c=1;tr[x].id=id;
tr[x].son[0]=tr[x].son[1]=0;tr[x].fa=fa;
tr[fa].son[big(d1,d2,tr[fa].d1,tr[fa].d2)?0:1]=x;
}
void rotate(int x)
{
int y=tr[x].fa,z=tr[y].fa,w,R,r;
w=tr[y].son[0]==x?1:0;
R=y;r=tr[x].son[w];
tr[R].son[1-w]=r;
if(r!=0) tr[r].fa=R;
R=z;r=x;
tr[R].son[tr[z].son[0]==y?0:1]=r;
if(r!=0) tr[r].fa=R;
R=x;r=y;
tr[R].son[w]=r;
if(r!=0) tr[r].fa=R;
update(y);update(x);
}
void splay(int x,int fa)
{
while(tr[x].fa!=fa)
{
int y=tr[x].fa,z=tr[y].fa;
if(z==fa) rotate(x);
else
if((tr[z].son[0]==y)==(tr[y].son[0]==x)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
if(fa==0) root=x;
}
int findid(LL d1,int d2)
{
int x=root;
while(1)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
if(big(d1,d2,tr[x].d1,tr[x].d2))
if(lc==0) break;
else x=lc;
else
if(rc==0) break;
else x=rc;
}
return x;
}
int findip(int k)
{
int x=root;
while(1)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
if(k<=tr[lc].c) x=lc;
else if(k>tr[lc].c+1) k-=(tr[lc].c+1),x=rc;
else break;
}
return x;
}
void ins(LL d1,int d2,int id,int tmp)
{
if(root==0){add(d1,d2,0,id,tmp);root=tmp;return;}
int x=findid(d1,d2);
add(d1,d2,x,id,tmp);
update(x);splay(x,0);
}
void del(int x)
{
splay(x,0);
if(tr[x].son[0]==0&&tr[x].son[1]==0){root=len=0;return;}
if(tr[x].son[0]!=0&&tr[x].son[1]==0){tr[tr[x].son[0]].fa=0;root=tr[x].son[0];return;}
if(tr[x].son[0]==0&&tr[x].son[1]!=0){tr[tr[x].son[1]].fa=0;root=tr[x].son[1];return;}
int p=tr[x].son[0];
while(tr[p].son[1]!=0) p=tr[p].son[1];
splay(p,x);root=p;tr[root].fa=0;
tr[root].son[1]=tr[x].son[1];
tr[tr[x].son[1]].fa=root;
update(root);
}
void solve(int l,int r)//让l,r这段区间独立出来
{
int x=findip(l),y=findip(r+2);
splay(x,0);splay(y,x);
}
bool first;
void print(int x)
{
if(tr[x].son[0]!=0) print(tr[x].son[0]);
int id=tr[x].id;
if(first) first=false;
else printf(" ");
for(int i=1;i<a[id].len;i++) printf("%c",a[id].s[i]);
if(tr[x].son[1]!=0) print(tr[x].son[1]);
}
int main()
{
scanf("%d",&n);
add(inf,-99999999,0,0,++len);add(-inf,99999999,1,0,++len);
root=1;string ch;
while(n--)
{
cin>>ch;
if(ch[0]=='+')
{
LL d1;scanf("%lld",&d1);
if(name[ch]==0)
{
name[ch]=++num;a[num].s=ch;a[num].id=++len;
ins(d1,++tot,num,len);a[num].len=ch.size();
}
else
{
int id=name[ch],x=a[id].id;del(x);
ins(d1,++tot,id,x);
}
}
else
if('A'<=ch[1]&&ch[1]<='Z')
{
ch[0]='+';int id=name[ch];
int x=a[id].id;splay(x,0);
printf("%d\n",tr[tr[x].son[0]].c);
}
else
{
int tmp=ch.size();int l=0;
for(int i=1;i<tmp;i++) l=l*10+ch[i]-'0';
int r=min(num,l+9);solve(l,r);
first=true;
print(tr[tr[root].son[1]].son[0]);
cout<<endl;
}
}
}