• 【bzoj1208】宠物收养所——treap


    第二道treap题,码完之后总是RE……查了两个多小时的错,对拍了三四份代码啊啊啊

    刚开始发现if(tree[k].l*tree[k].r==0)k=tree[k].l+tree[k].r;这一句写错了,但改完还是WA或RE……

    于是又找了接近两个小时的错啊啊啊,终于发现是左旋操作中的一个t打成了k,枉我之前还一直以为是del或者get_big写错了呢

    还是不够细心啊

    好了,言归正传。

    这道题由于题目说“同一时间呆在收养所中的,要么全是宠物,要么全是领养者”,那么就可以建一棵treap树(用一个变量ty储存当前树类型,即1或0),与当前树类型相同就加入该节点,不同就对比该值与前驱值差和后继值差的绝对值,取较小的一个(若相同则选前驱),接着ans加上该值(记得要取余mod!),然后del前驱或后继,最后得到的ans即为答案。

    具体细节看代码。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    const int mod=1000000;
    using namespace std;
    int n,root=0,ty,ans=0,size=0,tt,pp,a,b;
    struct point
    {
        int v,l,rnd,r;
    }tree[100002];
    void lturn(int &k)
    {
        int t=tree[k].r;
        tree[k].r=tree[t].l;
        tree[t].l=k;
        k=t;
    }
    void rturn(int &k)
    {
        int t=tree[k].l;
        tree[k].l=tree[t].r;
        tree[t].r=k;
        k=t;
    }
    void insert(int &k,int x)
    {
        if(k==0)
        {
            size++;k=size;
            tree[k].l=tree[k].r=0;
            tree[k].v=x;tree[k].rnd=rand();
            return;
        }
        if(x>tree[k].v)
        {
            insert(tree[k].r,x);
            if(tree[tree[k].r].rnd<tree[k].rnd)lturn(k);
        }
        else
        {
            insert(tree[k].l,x);
            if(tree[tree[k].l].rnd<tree[k].rnd)rturn(k);
        }
    }
    void del(int &k,int x)
    {
        if(k==0)return;
        if(tree[k].v==x)
        {
            if(tree[k].l*tree[k].r==0)k=tree[k].l+tree[k].r;
            else if(tree[tree[k].l].rnd<tree[tree[k].r].rnd)rturn(k),del(k,x);
            else lturn(k),del(k,x);
        }
        else if(tree[k].v<x)del(tree[k].r,x);
        else del(tree[k].l,x);
    }
    void get_big(int k,int x)
    {
        if(k==0)return;
        if(tree[k].v<=x)
        {
            tt=k;get_big(tree[k].r,x);
        }
        else get_big(tree[k].l,x);
    }
    void get_small(int k,int x)
    {
        if(k==0){return;}
        if(tree[k].v>x)
        {
            pp=k;get_small(tree[k].l,x);
        }
        else get_small(tree[k].r,x);
    }
    int main()
    {
        int num=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d",&a,&b);
            if(!num){size=0;root=0,insert(root,b),ty=a,num++;}
            else if(a==ty){
                insert(root,b);
                num++;
            }
            else 
            {
                tt=0;get_big(root,b);
                pp=0;get_small(root,b);
                if(!pp||(tt&&tree[tt].v&&b-tree[tt].v<=tree[pp].v-b)){ans=(ans+b-tree[tt].v)%mod;del(root,tree[tt].v);}
                else {ans=(ans+tree[pp].v-b)%mod;del(root,tree[pp].v);}
                num--;
            }
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    JS时间自动更新
    浏览器一般兼容问题
    实现笛卡尔心形线的重复循环绘制
    js判断是否为ie6以外的浏览器,若是,则调用相应脚本
    html+css+js实现标签页切换
    实现跨浏览器的背景渐变
    IE8支持HTML5的占位符placeholder
    JS打造的跟随鼠标移动的酷炫拓扑图案
    JS获取阴历阳历和星期
    svn up时提示跳过某节点
  • 原文地址:https://www.cnblogs.com/JKAI/p/6942171.html
Copyright © 2020-2023  润新知