[BZOJ]1056 和 1862 splay

可供复制的样例:

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);
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值