题解 P2286 【[HNOI2004]宠物收养场】
大家好,这个题我调了很久过了,所以想写题解
我用的平衡树是AVL树,平衡树界的老爷爷
这个树并不会很慢,主要是我初学,常数巨大
而且题目的 $ n = 80000$,可以接受
\(solution\):
开两颗平衡树,维护宠物和人,过多就插入自己的平衡树,过少就在对立平衡树中删除与 \(x\) 相差最小的。
也就是确定前驱后继
代码很长,但是操作是相同的,一半都是在复制粘贴
希望注意传参引用,少写一个调了很长时间
\(code:\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 80000+50;
const int mod = 1000000;
int ans;
inline void read(int &k) {
k=0;char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch<='9'&&ch>='0') k=k*10+ch-'0',ch=getchar();
}
namespace pet{
int root,cnt;
struct node{
int l,r,val,height,size;
}avl[N];
inline void newnode(int &now,int val) {
avl[now=++cnt].val=val,avl[now].size=1;
}
int factor(int now) {
return avl[avl[now].l].height-avl[avl[now].r].height;
}
void update(int now) {
avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
}
void zag(int &now) {
int r=avl[now].r;
avl[now].r=avl[r].l;
avl[r].l=now;
now=r;
update(avl[now].l),update(now);
}
void zig(int &now) {
int l=avl[now].l;
avl[now].l=avl[l].r;
avl[l].r=now;
now=l;
update(avl[now].r),update(now);
}
void check(int &now) {
int bf=factor(now);
if(bf>1) {
int lf=factor(now);
if(lf>0) zig(now);
else zag(avl[now].l),zig(now);
}else if(bf<-1) {
int rf=factor(now);
if(rf<0) zag(now);
else zig(avl[now].r),zag(now);
}else if(now) update(now);
}
void ins(int &now,int val) {
if(!now) newnode(now,val);
else if(avl[now].val>val) ins(avl[now].l,val);
else ins(avl[now].r,val);
check(now);
}
int find(int &now,int fa) {
int tmp;
if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
else tmp=find(avl[now].l,now),check(now);
return tmp;
}
void del(int &now,int val) {
if(avl[now].val==val) {
int l=avl[now].l,r=avl[now].r;
if(!l||!r) now=l+r;
else {
now=find(r,r);
if(now!=r) avl[now].r=r;
avl[now].l=l;
}
}else if(avl[now].val>val) del(avl[now].l,val);
else del(avl[now].r,val);
check(now);
}
int getrank(int val) {
int now=root,rank=1;
while(now) {
if(val<=avl[now].val) now=avl[now].l;
else rank+=avl[avl[now].l].size+1,now=avl[now].r;
}
return rank;
}
int getnum(int rank) {
int now=root;
while(now) {
if(rank==avl[avl[now].l].size+1) break;
else if(rank<=avl[avl[now].l].size) now=avl[now].l;
else rank-=avl[avl[now].l].size+1,now=avl[now].r;
}
return avl[now].val;
}
int search(int now,int val) {
if(!now) return false;
if(val==avl[now].val) return true;
else if(val<avl[now].val) return search(avl[now].l,val);
else return search(avl[now].r,val);
return false;
}
}
namespace human{
int root,cnt;
struct node{
int l,r,val,height,size;
}avl[N];
inline void newnode(int &now,int val) {
avl[now=++cnt].val=val,avl[now].size=1;
}
int factor(int now) {
return avl[avl[now].l].height-avl[avl[now].r].height;
}
void update(int now) {
avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
}
void zag(int &now) {
int r=avl[now].r;
avl[now].r=avl[r].l;
avl[r].l=now;
now=r;
update(avl[now].l),update(now);
}
void zig(int &now) {
int l=avl[now].l;
avl[now].l=avl[l].r;
avl[l].r=now;
now=l;
update(avl[now].r),update(now);
}
void check(int &now) {
int bf=factor(now);
if(bf>1) {
int lf=factor(now);
if(lf>0) zig(now);
else zag(avl[now].l),zig(now);
}else if(bf<-1) {
int rf=factor(now);
if(rf<0) zag(now);
else zig(avl[now].r),zag(now);
}else if(now) update(now);
}
void ins(int &now,int val) {
if(!now) newnode(now,val);
else if(avl[now].val>val) ins(avl[now].l,val);
else ins(avl[now].r,val);
check(now);
}
int find(int &now,int fa) {
int tmp;
if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
else tmp=find(avl[now].l,now),check(now);
return tmp;
}
void del(int &now,int val) {
if(avl[now].val==val) {
int l=avl[now].l,r=avl[now].r;
if(!l||!r) now=l+r;
else {
now=find(r,r);
if(now!=r) avl[now].r=r;
avl[now].l=l;
}
}else if(avl[now].val>val) del(avl[now].l,val);
else del(avl[now].r,val);
check(now);
}
int getrank(int val) {
int now=root,rank=1;
while(now) {
if(val<=avl[now].val) now=avl[now].l;
else rank+=avl[avl[now].l].size+1,now=avl[now].r;
}
return rank;
}
int getnum(int rank) {
int now=root;
while(now) {
if(rank==avl[avl[now].l].size+1) break;
else if(rank<=avl[avl[now].l].size) now=avl[now].l;
else rank-=avl[avl[now].l].size+1,now=avl[now].r;
}
return avl[now].val;
}
int search(int now,int val) {
if(!now) return false;
if(val==avl[now].val) return true;
else if(val<avl[now].val) return search(avl[now].l,val);
else return search(avl[now].r,val);
return false;
}
}
signed main() {
int n; cin>> n;
while(n--) {
int opt, x;
// scanf("%lld%lld",&opt, &x);
read(opt),read(x);
if(!opt) {
if(human::avl[human::root].size) {
if(human::search(human::root,x)) human::del(human::root,x);
else {
int pre=human::getnum(human::getrank(x)-1);
int nxt=human::getnum(human::getrank(x+1));
if(pre==0) { ans+=nxt-x,ans%=mod,human::del(human::root,nxt);continue;}
if(nxt==0) { ans+=x-pre,ans%=mod,human::del(human::root,pre);continue;}
if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,human::del(human::root,pre);
else ans+=nxt-x,ans%=mod,human::del(human::root,nxt);
}
}else pet::ins(pet::root,x);
}else {
if(pet::avl[pet::root].size) {
if(pet::search(pet::root,x)) pet::del(pet::root,x);
else {
int pre=pet::getnum(pet::getrank(x)-1);
int nxt=pet::getnum(pet::getrank(x+1));
if(pre==0) { ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);continue;}
if(nxt==0) { ans+=x-pre,ans%=mod,pet::del(pet::root,pre);continue;}
if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,pet::del(pet::root,pre);
else ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);
}
}else human::ins(human::root,x);
}
}
cout<<ans;
return 0;
}
题解 P2286 【[HNOI2004]宠物收养场】的更多相关文章
- 洛谷P2286 [HNOI2004]宠物收养场【Treap】题解+AC代码
题目传送门啦~啦~啦~ 题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的 ...
- P2286 [HNOI2004]宠物收养场
题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
- 洛谷P2286 [HNOI2004]宠物收养场
题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
- 洛谷 P2286 [HNOI2004]宠物收养场
题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
- Luogu P2286 [HNOI2004]宠物收养场
一道比较简单的直接Treap运用题目,思维难度和代码难度都不是很高. 题意有点长,我们仔细剖析一下题意发现以下几个关键: 任何时候收养站里只可能有人和宠物中的其中一种,或者都没有 如果只有宠物并有人来 ...
- 【题解】 [HNOI2004]宠物收养场(Splay)
懒得复制,戳我戳我 Solution: \(Splay\)板子,注意交换的地方,然后就是注意不要越界node[x],应该是\(node[now]\),其次就是数组可以开大点 Code: //It is ...
- [HNOI2004]宠物收养场 Treap前驱后继
凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领 ...
- 洛谷P2286 [HNOI2004]宠物收养所 [STL,平衡树]
题目传送门 宠物收养所 题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的 ...
- BZOJ1208[HNOI2004]宠物收养场——treap
凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领 ...
- [HNOI2004]宠物收养场 BZOJ1208 splay tree
题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
随机推荐
- ARTS-S 在docker中运行本地脚本
很多情况是本地没有编译环境,但docker中有编译环境.想编译本地代码,就要把本地的代码和编译脚本映射到docker中,脚本如下: docker run \ -it \ -v /Users/usern ...
- jquery (内置遍历数组的函数,事件)
内置遍历数组的函数: 1. $.map(array, function() { }); 取到数组或者对象array中每一项进行遍历 然后在function中处理: var attr = [1,2,3 ...
- Python3 网络编程基础1
目录 开发架构 C/S架构 B/S架构 OSI模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 TCP协议 socket 开发架构 C/S架构 client 和 server, 既客户 ...
- 非线性函数的最小二乘拟合及在Jupyter notebook中输入公式 [原创]
突然有个想法,能否通过学习一阶RC电路的阶跃响应得到RC电路的结构特征——时间常数τ(即R*C).回答无疑是肯定的,但问题是怎样通过最小二乘法.正规方程,以更多的采样点数来降低信号采集噪声对τ估计值的 ...
- CodeForces - 556D Case of Fugitive (贪心+排序)
Andrewid the Android is a galaxy-famous detective. He is now chasing a criminal hiding on the planet ...
- 《Java练习题》进阶练习题(二)
编程合集: https://www.cnblogs.com/jssj/p/12002760.html 前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题. [程序58 ...
- mac-安装java、安装maven
首先检查自己的设备是否已经安装了jdk,在cmd终端输入,如已安装出现对应的版本信息,未安装弹出提示窗,官方网址:http://www.oracle.com/technetwork/java/java ...
- vue路由基础总结
1.创建项目 为了练习路由 这里没有选择路由 就选了Bable 自己一步一步的配置 加深印象. 然后下载路由 npm install vue-router --save 2.基础配置 src文件下新建 ...
- error: src refspec test does not match any.
我在本地创建了新分支test并提交到github上 错误信息如下: error: src refspec test does not match any. error: failed to push ...
- linux 系统账户 和 普通账户 的区别
最近使用 useradd -r 选项进行创建账户,用于测试,对-r 选项不是很明白,下面记录一些调研的过程: -r, --system Create a system account. System ...