NHOI 2004 宠物收养所 splay解法

简介:

1208: [HNOI2004]宠物收养所

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 3047   Solved: 1098
[ Submit][ Status]

Description

最近,阿Q开了一间宠物收养所。收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少。 1. 被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为a,那么它将会领养一只目前未被领养的宠物中特点值最接近a的一只宠物。(任何两只宠物的特点值都不可能是相同的,任何两个领养者的希望领养宠物的特点值也不可能是一样的)如果有两只满足要求的宠物,即存在两只宠物他们的特点值分别为a-b和a+b,那么领养者将会领养特点值为a-b的那只宠物。 2. 收养宠物的人过多,假若到来一只被收养的宠物,那么哪个领养者能够领养它呢?能够领养它的领养者,是那个希望被领养宠物的特点值最接近该宠物特点值的领养者,如果该宠物的特点值为a,存在两个领养者他们希望领养宠物的特点值分别为a-b和a+b,那么特点值为a-b的那个领养者将成功领养该宠物。 一个领养者领养了一个特点值为a的宠物,而它本身希望领养的宠物的特点值为b,那么这个领养者的不满意程度为abs(a-b)。【任务描述】你得到了一年当中,领养者和被收养宠物到来收养所的情况,希望你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。

Input

第一行为一个正整数n,n<=80000,表示一年当中来到收养所的宠物和领养者的总数。接下来的n行,按到来时间的先后顺序描述了一年当中来到收养所的宠物和领养者的情况。每行有两个正整数a, b,其中a=0表示宠物,a=1表示领养者,b表示宠物的特点值或是领养者希望领养宠物的特点值。(同一时间呆在收养所中的,要么全是宠物,要么全是领养者,这些宠物和领养者的个数不会超过10000个)

Output

仅有一个正整数,表示一年当中所有收养了宠物的领养者的不满意程度的总和mod 1000000以后的结果。

Sample Input

5
0 2
0 4
1 3
1 2
1 5

Sample Output

3
(abs(3-2) + abs(2-4)=3,最后一个领养者没有宠物可以领养)

HINT

Source

[ Submit][ Status] 

HOME Back

删掉节点,每次都把节点的前驱转到根,把后继转到根的子节点,这样要删的点就是根的右儿子的左儿子,直接删掉就行了。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mm=10005;
const int oo=2e9;
struct SplayTree
{
    int son[mm][2],far[mm],val[mm],sum[mm];
    int rt,size;
    void PushUp(int x)
    {
        sum[x]=sum[son[x][0]]+sum[son[x][1]]+1;
    }
    void Link(int x,int y,int c)
    {
        far[x]=y,son[y][c]=x;
    }
    void Rotate(int x,int c)
    {
        int y=far[x];
        Link(x,far[y],son[far[y]][1]==y);
        Link(son[x][!c],y,c);
        Link(y,x,!c);
        PushUp(y);
    }
    void Splay(int x,int g)
    {
        for(; far[x]!=g;)
        {
            int y=far[x],cx=(son[y][1]==x),cy=(son[far[y]][1]==y);
            if(far[y]==g)Rotate(x,cx);
            else
            {
                if(cx==cy)Rotate(y,cy);
                else Rotate(x,cx);
                Rotate(x,cy);
            }
        }
        PushUp(x);
        if(!g)rt=x;
    }
    void NewNode(int y,int &x,int a)
    {
        x=++size;
        far[x]=y,val[x]=a,sum[x]=1;
        son[x][0]=son[x][1]=0;
    }
    void Insert(int a)
    {
        int x=rt;
        while(son[x][val[x]<a])x=son[x][val[x]<a];
        NewNode(x,son[x][val[x]<a],a);
        Splay(size,0);
    }
    void Prepare()
    {
        memset(sum,0,sizeof(sum));
        NewNode(size=0,rt,-oo);
        NewNode(rt,son[rt][1],oo);
        sum[rt]=2;
    }
    int Suc(int a)
    {
        int x=rt,ret=oo;
        while(x)
        {
            if(val[x]==a) return a;
            if(val[x]>a) ret=min(ret,val[x]);
            x=son[x][val[x]<a];
        }
        return ret;
    }
    int Pre(int a)
    {
        int x=rt,ret=-oo;
        while(x)
        {
            if(val[x]==a)return a;
            if(val[x]<a)ret=max(ret,val[x]);
            x=son[x][val[x]<a];
        }
        return ret;
    }
    int Find(int a)
    {
        int x=rt,ans=0;
        while(x)
        {
            if(val[x]==a) ans=x;
            x=son[x][val[x]<a];
        }
        return ans;
    }
    void Select(int k,int g)
    {
        int x=rt;
        sum[0]=0;
        while(sum[son[x][0]]+1!=k)
        {
            if(sum[son[x][0]]+1>k) x=son[x][0];
            else k-=(sum[son[x][0]]+1),x=son[x][1];
        }
        Splay(x,g);
    }
    void Delete(int a)
    {
        int x=Find(a);
        Splay(x,0);
        int y=sum[son[x][0]];
        Select(y,0);
        Select(y+2,rt);
        son[son[rt][1]][0]=0;
        PushUp(son[rt][1]);
        PushUp(rt);
        size--;
    }
    void display(int x)
    {
        if(x==0)
            return;
        display(son[x][0]);
        cout<<"now: "<<x<<"  "<<val[x]<<" sum: "<<sum[x]<<" ls: "<<son[x][0]<<" rs: "<<son[x][1]<<endl;
        display(son[x][1]);
    }
} spt;
int main()
{
    int n,a,b,ans,f;
    while(~scanf("%d",&n))
    {
        ans=0;
        spt.Prepare();
        int size=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&a,&b);
            if(size==0||a==f)
                size++,spt.Insert(b),f=a;
            else
            {
                int p=spt.Pre(b),q=spt.Suc(b);
                if(b-p<=q-b)ans+=b-p,spt.Delete(p);
                else ans+=q-b,spt.Delete(q);
                if(ans>=1000000)ans%=1000000;
                size--;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


目录
相关文章
|
5月前
|
算法
基础算法-去重字符串,辗转相除法,非递归前序遍历二叉树题型分析
基础算法-去重字符串,辗转相除法,非递归前序遍历二叉树题型分析
|
6月前
|
算法
一题学会BFS和DFS,手撕不再怕
一题学会BFS和DFS,手撕不再怕
|
6月前
八皇后问题与其深度优先搜索 (DFS) 解法
八皇后问题与其深度优先搜索 (DFS) 解法
74 1
|
算法
并查集模板题
并查集模板题
48 0
|
存储 C++
【PAT甲级 - C++题解】1138 Postorder Traversal
【PAT甲级 - C++题解】1138 Postorder Traversal
60 0
洛谷P1443 马的遍历——广搜
洛谷P1443 马的遍历——广搜
76 0
|
算法 索引
刷爆 LeetCode 周赛 339,贪心 / 排序 / 拓扑排序 / 平衡二叉树
大家好,我是小彭。 上周末是 LeetCode 第 339 场周赛,你参加了吗?这场周赛覆盖的知识点比较少,前三题很简单,第四题上难度。
99 0
51nod 1711 平均数(二分 + 树状数组好题)
51nod 1711 平均数(二分 + 树状数组好题)
95 0
|
算法 定位技术
BFS算法模板与练习
BFS算法模板与练习
125 0
Codeforces1153——D. Serval and Rooted Tree(思维好题+dfs+贪心)
Codeforces1153——D. Serval and Rooted Tree(思维好题+dfs+贪心)
129 0
Codeforces1153——D. Serval and Rooted Tree(思维好题+dfs+贪心)