题目描述

最近,阿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)。

你的任务:你得到了一年当中,领养者和被收养宠物到来收养所的情况,希望你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。

输入格式

第一行为一个正整数n,n <= 80000,表示一年当中来到收养所的宠物和领养者的总数。

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

输出格式

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

分析

可以很容易看出来,这是一道平衡树的题,就用最常见的Splay来写。一开始想的是开两棵平衡树,分别维护宠物与领养者,虽然可做,但太繁琐。于是就用一棵平衡树在宠物与领养者之间切换。用两个变量来维护宠物和领养者的数量,若读入的为宠物,则检查领养者的数量是否为0,若为0,则将其Insert进平衡树,并将宠物的数量加1;否则说明当前这棵平衡树是领养者的,于是在里面查前驱后继,更新答案,将领养者的数量减1。若读入为领养者类似。这样就可以在宠物与领养者之间来回切换了。

由分析可见,此题用STL set也可以写,且更方便一些。

代码

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int Mod=1000000,N=80008;
const int INF=0x7fffffff/2;
int n,x,p,num[2];
long long ans;
#define lc(x) (a[x].ch[0])
#define rc(x) (a[x].ch[1])
#define fa(x) (a[x].prt)
#define sz(x) (a[x].size)
#define vl(x) (a[x].val)
#define ct(x) (a[x].cnt)
#define nt(x,p) (a[x].ch[p])
#define root a[0].ch[1]
struct BST {int ch[2],prt;int val,cnt,size;
}a[N];
int tot;
void Updata(int x) {sz(x)=sz(lc(x))+sz(rc(x))+ct(x);
}
int Identify(int x) {return lc(fa(x))==x?0:1;
}
void Connect(int son,int pt,int lr) {fa(son)=pt;nt(pt,lr)=son;
}
void Rotate(int x) {int y=fa(x);int mroot=fa(y);int mson=Identify(y);int yson=Identify(x);int B=nt(x,yson^1);Connect(B,y,yson);Connect(y,x,yson^1);Connect(x,mroot,mson);Updata(y);Updata(x);
}
void Splay(int at,int to) {to=fa(to);while (fa(at)!=to) {int up=fa(at);if (fa(up)==to) Rotate(at);else if (Identify(at)==Identify(up)) {Rotate(up);Rotate(at);} else {Rotate(at);Rotate(at);}}
}
int Next(int val) {int p=root,res=INF,ans=-1;while (p) {if (vl(p)==val) {res=vl(p);ans=p;break;}if (vl(p)>val&&vl(p)<res) {res=vl(p);ans=p;}if (val<vl(p)) p=lc(p);else p=rc(p);}if (ans!=-1) Splay(ans,root);return ans;
}
int Pre(int val) {int p=root,res=-INF,ans=-1;while (p) {if (vl(p)==val) {res=vl(p);ans=p;break;}if (vl(p)<val&&vl(p)>res) {res=vl(p);ans=p;}if (val<vl(p)) p=lc(p);else p=rc(p);}if (ans!=-1) Splay(ans,root);return ans;
}
int New(int val,int prt) {tot++;fa(tot)=prt;vl(tot)=val;sz(tot)=ct(tot)=1;return tot;
}
void Insert(int val) {if (tot==0) {root=New(val,0);return;}int p=root,nxt;while (1) {sz(p)++;if (vl(p)==val) {ct(p)++;Splay(p,root);return;}nxt=(val<vl(p)?0:1);if (!nt(p,nxt)) {int t=New(val,p);nt(p,nxt)=t;Splay(t,root);return;}p=nt(p,nxt);}
}
int Find(int val) {int p=root,nxt;while (p) {if (vl(p)==val) return p;nxt=(val<vl(p)?0:1);p=nt(p,nxt);}return -1;
}
void Remove(int val) {int p=Find(val);if (p==-1) return;if (ct(p)>1) {sz(p)--;ct(p)--;return;}Splay(p,root);int l=lc(p),r=rc(p);if (!l) {root=r;fa(root)=0;return;}while (rc(l)) l=rc(l);Splay(l,lc(root));Connect(r,l,1);Connect(l,0,1);Updata(l);
}
int main() {scanf("%d",&n);for (int i=1;i<=n;i++) {scanf("%d%d",&p,&x);if (!num[p^1]) {Insert(x);num[p]++;} else {int t1=Pre(x),t2=Next(x),v1=INF,v2=INF;if (t1!=-1) v1=x-vl(t1);if (t2!=-1) v2=vl(t2)-x;if (v1<=v2) {ans+=v1;Remove(vl(t1));} else {ans+=v2;Remove(vl(t2));}num[p^1]--;}ans=ans%Mod;}printf("%lld",ans);return 0;
}

「HNOI2004」 宠物收养所 - 平衡树Splay相关推荐

  1. 【HNOI2004】宠物收养所

    [HNOI2004]宠物收养所 [题目描述] 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要 ...

  2. B1208 [HNOI2004]宠物收养所 平衡树||set (滑稽)

    这个题是一道splay裸题,但是我不太会写,所以用set直接水过去!!!哈哈哈哈,美滋滋. set总结: set是一个集合,然后里面没用重复的元素.里面有一些函数: begin()     ,返回se ...

  3. bzoj1208【HNOI2004】宠物收养所

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec   Memory Limit: 162 MB Submit: 5923   Solved: 2296 [ Submit ...

  4. 【codevs1285】【BZOJ1208】宠物收养所,splay练习

    传送门1 传送门2 写在前面:我自己也会被写进机房大事记-- 思路:很裸的splay练习,只涉及查前驱后继和删除操作,加一个标记记录现在是宠物多还是人多即可 注意: 1.查询和调用前驱后继时可能两者同 ...

  5. 洛谷P2286 [HNOI2004]宠物收养所 [STL,平衡树]

    题目传送门 宠物收养所 题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的 ...

  6. cogs62 [HNOI2004] 宠物收养所

    cogs62 [HNOI2004] 宠物收养所 啦啦啦啦 不维护区间的平衡树题都是树状数组+二分练手题! 不会的参考我的普通平衡树的多种神奇解法之BIT+二分答案 // It is made by X ...

  7. 洛谷 P2286 [HNOI2004]宠物收养场

    题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...

  8. BZOJ 1208: [HNOI2004]宠物收养所

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7684  Solved: 3042 [Submit][S ...

  9. NHOI 2004 宠物收养所 splay解法

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec   Memory Limit: 162 MB Submit: 3047   Solved: 1098 [ Submit ...

最新文章

  1. 基于Dlib、OpenCV开发人脸识别程序的开发建议
  2. Oracle创建序列,删除序列,得到序列的例子
  3. mpvue外卖小程序
  4. 170 道 Python 爬虫面试题(2019 版)
  5. 利用python 对比相似度_头条、油条商标有多像?Python检测发现相似度高达98.4%
  6. 了解jQuery技巧来提高你的代码
  7. AFNetworking网络请求与图片上传工具(POST)
  8. 学到了!MySQL 8 新增的「隐藏索引」真不错
  9. 单独组件_阿里P8年薪百万大牛-教你打造一个Android组件化开发框架
  10. Pokémon Go呼应设计:让全世界玩家疯狂沉迷
  11. 内存陷阱 驯服C++中的野指针
  12. 『开发技巧』MacbookM1芯片深度学习环境配置最全教程:简明安装开发TensorFlow与PyTorch
  13. struts2之拦截器详解
  14. centos离线安装谷歌浏览器flash-player
  15. (015) 自动加载
  16. 【数据仓库与OLAP技术】期末复习+考题
  17. oracle根据汇总报表计算结余
  18. EcmaScript 2022中的新特性
  19. 002输出一个正方形
  20. alexnet 模型详解以及模型的可视化

热门文章

  1. 数字艺术藏品系统开发
  2. 做一个网站一般需要多少费用
  3. 目标检测:YOLO V1、YOLO V2、YOLO V3 算法
  4. UIPATH 发送SMTP电子邮件
  5. 软件测试的原则有哪些?来自十年测试老鸟的总结
  6. 【知识图谱】构建《射雕三部曲》图谱(CSV文件导入)
  7. oracle11g 没有scott,Oracle11g中没有scott用户怎么办啊???
  8. 寒假第三周学习总结与反思
  9. springcloud gateway断路器抛的错default failed and fallback disabled
  10. JVM 内存模型、垃圾回收