这是题目链接

大家好,这个题我调了很久过了,所以想写题解

我用的平衡树是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]宠物收养场】的更多相关文章

  1. 洛谷P2286 [HNOI2004]宠物收养场【Treap】题解+AC代码

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

  2. P2286 [HNOI2004]宠物收养场

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

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

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

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

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

  5. Luogu P2286 [HNOI2004]宠物收养场

    一道比较简单的直接Treap运用题目,思维难度和代码难度都不是很高. 题意有点长,我们仔细剖析一下题意发现以下几个关键: 任何时候收养站里只可能有人和宠物中的其中一种,或者都没有 如果只有宠物并有人来 ...

  6. 【题解】 [HNOI2004]宠物收养场(Splay)

    懒得复制,戳我戳我 Solution: \(Splay\)板子,注意交换的地方,然后就是注意不要越界node[x],应该是\(node[now]\),其次就是数组可以开大点 Code: //It is ...

  7. [HNOI2004]宠物收养场 Treap前驱后继

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

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

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

  9. BZOJ1208[HNOI2004]宠物收养场——treap

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

  10. [HNOI2004]宠物收养场 BZOJ1208 splay tree

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

随机推荐

  1. cl创建opencv程序

    环境 win8 VS2017或VS2013 opencv 3.2.0 配制环境变量 解压opencv到某个目录,比如D:\Program\Uninstall,把设置OPENCV_HOME为D:\Pro ...

  2. 【数据结构06】二叉平衡树(AVL树)

    目录 一.平衡二叉树定义 二.这货还是不是平衡二叉树? 三.平衡因子 四.如何保持平衡二叉树平衡? 五.平衡二叉树插入节点的四种情况 六.平衡二叉树操作的代码实现 七.AVL树总结 @ 一.平衡二叉树 ...

  3. Day 01 Markdown基本语法

    目录 Markdown基本语法 标题 一级标题 二级标题 三级标题 加粗 斜体 高亮 上标 下标 代码引用(>式) 代码引用(```式) 代码引入(`式) 插入链接(链接显示) 插入链接(链接描 ...

  4. 【MobX】391- MobX 入门教程(下)

    点击上方"前端自习课"关注,学习起来~ 三.MobX 常用 API 介绍 3. 修改可观察数据 在上一部分内容中,我们了解到,对可观察的数据做出反应的时候,需要我们手动修改可观察数 ...

  5. 002_Java语言基础

    ------------恢复内容开始------------ 存储的基本单元:byte: 1 byte = 8 bit(位) 1 KB = 1024 byte 1 MB = 1024 KB 1 GB ...

  6. 关于Java调用接入微信、支付宝支付提现

    前言: 本篇文章介绍关于自己写的一个集成微信.支付宝的支付.提现等功能的介绍,本项目已在码云上进行开源,欢迎大家一起来进行改造,使进行更好的创新供大家使用:也有对应的pom文件坐标可以导入,因目前不知 ...

  7. TP框架对数据库的操作

    1.添加数据       1.1添加一条数据 $user = new User; $user->name = 'thinkphp'; $user->email = 'thinkphp@qq ...

  8. SpringCloud -创建统一的依赖管理

    场景 Spring Cloud 为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,控制总线,一次性 Token,全居琐,Leader 选举,分布式 Session,集群状态)中快速构 ...

  9. JS---DOM---事件冒泡和阻止事件冒泡,总结事件

    事件冒泡: 多个元素嵌套, 有层次关系 ,这些元素都注册了相同的事件, 如果里面的元素的事件触发了, 外面的元素的该事件自动的触发了     事件有三个阶段: 1.事件捕获阶段  :从外向内 2.事件 ...

  10. composer入门 一些简单常用的命令介绍

    composer是什么 composer是PHP的插件依赖管理工具,我个人感觉和java的Maven.Gradle很类似. Windows OS下安装composer 参考: https://www. ...