题解 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
题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
随机推荐
- 【Eureka】服务端和客户端
[Eureka]服务端和客户端 转载:https://www.cnblogs.com/yangchongxing/p/10778357.html Eureka服务端 1.添加依赖 <?xml v ...
- docker-compose编排参数详解
一.前言 Compose是一个用于定义和运行多容器Docker应用程序的工具.使用Compose,您可以使用YAML文件来配置应用程序的服务.然后,使用单个命令,您可以从配置中创建并启动所有服务. C ...
- hdu 2955 Robberies (01背包好题)
Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- css设置使文字显示2行多余的为省略号。。。
.title{ font-size: .7rem; line-height: 1.5rem; overflow: hidden; /** 隐藏超出的内容 **/ word-break: break-a ...
- Windows下mysql-5.7.28下载、安装、配置教程
最近需要更换mysql数据库的版本,写一篇文章,记录一下 一.下载mysql数据库 mysql的下载共有两种,一种是zip压缩文件,另一种是msi安装程序 官方5.7版本zip压缩文件下载页面 官方5 ...
- orleans 2.0 进阶之自定义持久化储存
一丶简单介绍下目录结构和项目依赖,如图 二丶主要核心自定义代码 1. 添加自定义实现类 CustomProvider public class CustomProvider : IGrainStora ...
- 原生js复制粘贴上传图片前后台代码,兼容firebox,chrome, ie11,亲测有效
需求:粘贴上传图片,截图工具,右键粘贴,或者ctrl+v粘贴 方法1:可直接套用富文本框的图片上传功能,完成复制粘贴 缺点:麻烦,样式难控制 方法2:用原生js完成,以下案例基于此,样式请自己动手调整 ...
- 学生选课系统v1.0
最近两天写了下老师课上留的作业:学生选课系统.感觉自己写的特别麻烦,思路特别不清晰,平常自己总会偷懒,一些太麻烦细节的功能就不去实现了,用简单的功能来替代,直到自己这回写完这个系统(但自己写的比较lo ...
- Windows Server 2012操作系统实用技巧
1.在桌面显示“计算机” 方法一:控制面板中输入“桌面图标”搜索之后点击显示下面的“显示或隐藏桌面上的通用图标”: 方法二:WIn+R,在运行框中输入rundll32.exe shell32.dll, ...
- 代码管理平台之git
yum install -y gitmkdir -p /date/gitrootcd !$git init git add 1.txtgit commit -m "add 1.txt&quo ...