【bzoj1862】[ZJOI2006]GameZ游戏排名系统

7 篇文章 0 订阅
2 篇文章 0 订阅

这道题我一定要吐槽!
简直醉了这道题,我调了整整半天。
从下午3点调到了晚上八点,其实尽管我写的特别丑,但是我差不多6点吃饭之前就写对了,交上去WA,之后改了几个地方实际AC了,但是我并没有交,而是要来了数据换cena测,在测的时候可能是乱复制粘贴搞得我insert函数里的return写成了int,然后崩溃的几个小时就开始了,我用cena+面对数据编程1个多小时发现没有问题,但用cena就是会崩溃访问无效内存,后来我发现了那个错误,改了回来之后因为想得到feedback,我没有在bzoj上交,而是去洛谷交了,结果TLE了三个点!!!当晚立马发说说,说自己splay人傻自带大常数,发现题解里有个人用递归版的splay过了(话说我真的第一次见到递归版的splay,以前只听zyz说过),但是复制粘贴他的程序测了一遍发现他根本就是个TLE的,然后我尝试把map换成trie树,还是不过,弃题去睡了,然后第二天去学校的路上突然想到洛谷主站是不开O2的,但是bzoj是开O2的,突然懂了,心中一万头草泥马奔过,回学校立马上大牛分站交了一发,我去比递归版的那个常数都小,简直要哭了
但是交在bzoj上收获了了人生中的第一个PE,每次询问排名的最后多打了一个空格,用子树大小控制了一下,成功的AC了,泪奔.
好了说点正经的,贴一下题解QAQ,其实就是hash+Splay啦,昨天燃起学treap的想法今天过了之后又熄灭了(笑),用map不会卡常就尽情的用咯,感觉hash的话250000hash函数选的不好也是可能冲突的把,双hash说不定比map还慢= =(其实当然不会,只是自我安慰).

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
const int N=250010,inf=0x7fffffff;
int n,m,sz,root,tot,ed;
int ch[N][2],fa[N],size[N],key[N],score[N];
map<string,int>hs;
map<int,string>ys;
string name;
inline void clear(int x){ch[x][0]=ch[x][1]=fa[x]=size[x]=key[x]=0;}
inline int get(int x){return ch[fa[x]][1]==x;}
inline void updata(int x){if (x)size[x]=(ch[x][0]?size[ch[x][0]]:0)+(ch[x][1]?size[ch[x][1]]:0)+1;}
inline void rotate(int x)
{
    int old=fa[x],oldf=fa[old],which=get(x);
    ch[old][which]=ch[x][which^1];fa[ch[x][which^1]]=old;
    ch[x][which^1]=old;fa[old]=x;fa[x]=oldf;
    if (oldf)ch[oldf][ch[oldf][1]==old]=x;
    updata(old);updata(x);
}
inline void splay(int x,int tar)
{
    for (int old;(old=fa[x])!=tar;rotate(x))
    if (fa[old]!=tar)rotate(get(old)==get(x)?old:x);
    if (!tar)root=x;
}
inline int insert(int x)
{
    if (!root){root=++sz;ch[sz][0]=ch[sz][1]=fa[sz]=0;size[sz]=1;key[sz]=x;return sz;}
    int now=root,old=0; 
    while(1)
    {
        old=now;
        now=ch[now][x>key[now]];
        if (!now)
        {
            fa[++sz]=old;
            ch[sz][0]=ch[sz][1]=0;
            ch[old][x>key[old]]=sz;
            size[sz]=1;
            key[sz]=x;
            splay(sz,0);
            break;
        }
    }
    return sz;
}
inline int pre()
{
    int now=ch[root][0];
    while(ch[now][1])now=ch[now][1];
    return now;
}
inline void del(int x)
{
    splay(x,0);
    if (!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
    if (!ch[root][1]){int oldroot=root;root=ch[root][1];fa[root]=0;clear(oldroot);return;}
    if (!ch[root][0]){int oldroot=root;root=ch[root][0];fa[root]=0;clear(oldroot);return;}
    int leftbig=pre(),oldroot=root;
    splay(leftbig,0);
    ch[root=leftbig][1]=ch[oldroot][1];
    fa[ch[oldroot][1]]=root;
    clear(oldroot);
}
inline int findnth(int x)
{
    int now=root;
    while(1)
    {
        if (ch[now][1]&&size[ch[now][1]]>=x)now=ch[now][1];
        else 
        {
            int temp=1;
            temp+=ch[now][1]?size[ch[now][1]]:0;
            if (x<=temp){splay(now,0);return now;} 
            now=ch[now][0];
            x-=temp;
        }
    }
}
inline void print(int now)
{
    if (ch[now][1])print(ch[now][1]);
    ed--;
    string s=ys[now];
    int len=s.length();
    for (int i=0;i<len;++i)
    putchar(s[i]);if (ed) printf(" ");
    if (ch[now][0])print(ch[now][0]);
}
inline void dfs(int now)
{
    for (int now=1;now<=sz;++now)
    cout<<now<<' '<<ys[now]<<' '<<fa[now]<<' '<<size[now]<<' '<<ch[now][0]<<' '<<ch[now][1]<<' '<<key[now]<<endl;
}
inline void solve(int x)
{
    int l=x;
    int r=min(x+9,tot)+2;
    int aa=findnth(l);
    int bb=findnth(r);
    splay(bb,0);
    splay(aa,bb);
    ed=size[ch[ch[root][1]][0]];
    print(ch[ch[root][1]][0]);
    printf("\n");
}
int main()
{
//    freopen("std.in","r",stdin);
//   freopen("std.out","w",stdout);
    tot=0;
    register int val;
    hs.clear();ys.clear();
    scanf("%d",&n);
    insert(-inf);
    insert(inf);
    for (int i=1;i<=n;++i)
    {
        char c;
        while(c=getchar(),c!='+'&&c!='?');
        if (c=='+')
        {
            name="";
            char cc;
            while(1)
            {
                cc=getchar();
                if (cc>'Z'||cc<'A')break;
                name+=cc;
            }
            scanf("%d",&val);
            if (hs[name]==0)
            {
                insert(val);
                score[sz]=val;
                hs[name]=sz;
                ys[sz]=name;
                ++tot;
            }
            else 
            {
                int id=hs[name];
                del(id);
                score[id]=0;
                id=insert(val);
                score[hs[name]=id]=val;
                ys[id]=name;
           }
        }
        else 
        {
            val=0;
            char cc=getchar();
            if (cc>='0'&&cc<='9')
            {
                val=cc-'0';
                while(cc=getchar(),cc>='0'&&cc<='9')val=(val<<3)+(val<<1)+cc-'0';
               solve(val);
            }
            else 
            {
                name="";
                name+=cc;
                while(1)
                {    
                    cc=getchar();
                    if (cc>'Z'||cc<'A')break;
                    name+=cc;
                }
                int id=hs[name];
                splay(id,0);
                printf("%d\n",size[ch[id][1]]);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值