题解 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
题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
随机推荐
- Jenkins-部署java代码项目
实验环境: Jenkins:192.168.1.12 tomcat:192.168.1.7 一.新建远程代码Java项目仓库 说明:这边测试是在coding上注册账户,建立远程仓库,codin ...
- 【hibernate】应用程序级别的视图
[hibernate]应用程序级别的视图 转载:https://www.cnblogs.com/yangchongxing/p/10361281.html 在没有数据库修改权限时,像创建视图可以使用 ...
- 基于 HTML5 WebGL 构建智能数字化城市 3D 全景
前言 自 2011 年我国城镇化率首次突破 50% 以来,<新型城镇化发展规划>将智慧城市列为我国城市发展的三大目标之一,并提出到 2020 年,建成一批特色鲜明的智慧城市.截至现今,全国 ...
- Vue ---- vue的基本使用 文本/事件/属性指令 补充: js面向对象 js函数
目录 日考题(知识点)
- ThinkPhp RBAC实现原理
RBAC是英文Role-Based Access Control的缩写,是基于角色访问进行控制的机制.意思是给每个用户设定一个角色,然后根据这个角色来判断用户的权限. 在此基于ThinkPhp的MVC ...
- flutter学习之环境配置
1.Android SDK通常目录: 用户->用户名->AppData->Local=>Android->Sdk 2.不知道的情况下,打开Android Studio,然 ...
- 防止DataGridview闪烁
在Load事件中加入 typeof(DataGridView).InvokeMember("DoubleBuffered", BindingFlags.NonPublic | Bi ...
- super performSelector: 解决调用父类私有方法的问题
super performSelector: 解决objc调用父类私有方法的问题 Objc中[super performSelector: ...]并不会像其他语言一样能良好的工作.super只是编译 ...
- inux 资源监控分析-pidstat
pidstat是sysstat工具的一个命令,用于监控全部或指定进程的cpu.内存.线程.设备IO等系统资源的占用情况.pidstat首次运行时显示自系统启动开始的各项统计信息,之后运行pidstat ...
- 记druid 在配置中心下的一个大坑: cpu 达到 100%
把我们的dubbo 应用移步到配置中心上去之后,发现我们的应用过一段时间就会出现cpu 100%的情况 (大概是12个小时),一开始cpu占用是2-5% 的样子,什么都没做,后面竟然用尽了cpu.. ...