fjutacm 2492 宠物收养所 : Splay 模板 O(nlogn)
/**
problem: http://www.fjutacm.com/Problem.jsp?pid=2492
Splay blog: https://tiger0132.blog.luogu.org/slay-notes
函数介绍:
内部函数:
root为指针, x为数值
bool check(int root):返回当前结点为父节点的左结点还是右结点(0为左结点,1为右结点)
void pushUp(int root):旋转后维护结点信息
void rotate(int root):关键函数,旋转结点
void splay(int root, int target = 0):Splay核心,将root结点旋转至target子结点,target为0则旋转到树根
void find(int x): 将数值为x的结点旋转至树根
int pre(int x):寻找数值为x的结点的前驱结点,返回指针
int succ(int x):寻找数值为x的结点的后继节点,返回指针
外部函数:
void clear():清空平衡树
void insert(T x):插入数值为x的数
int rank(T x):返回数值为x的数为第几小
T preAns(T x):返回刚好比数值x小的数是多少
T succAns(T x):返回刚好比数值x大的数是多少
T kth(int k):返回第k小的数是多少
void remove(T x):删除数值为x的结点,如果有多个则数量-1
T top(T x):如果有数值为x的结点返回x,否则返回其他数
int getAllSize():返回平衡树中有多少个数
**/ #include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std; typedef long long ll;
const ll MOD = ; template<typename T>
class Splay{
const static int MAXN = ;
const static T INF = 0x3f3f3f3f3f3f3f3fLL;
private:
struct Node{
int ch[];
int cnt, size, parent;
T val;
}node[MAXN];
int treeroot, sign, allSize;
queue<int> freeMemory;
bool check(int root){ /// right return 1 else return 0
return node[node[root].parent].ch[] == root;
}
void pushUp(int root){
node[root].size = node[node[root].ch[]].size + node[node[root].ch[]].size + node[root].cnt;
}
void rotate(int root){
int father = node[root].parent, grandpa = node[father].parent, direction = check(root), child = node[root].ch[direction^];
node[father].ch[direction] = child; node[child].parent = father;
node[grandpa].ch[check(father)] = root; node[root].parent = grandpa;
node[root].ch[direction^] = father; node[father].parent = root;
pushUp(father); pushUp(root);
}
void splay(int root, int target = ){ /// if target == 0 then root to treeroot
while(node[root].parent != target){
int father = node[root].parent, grandpa = node[father].parent;
if(grandpa != target){
if(check(root) == check(father)) rotate(father);
else rotate(root);
}
rotate(root);
}
if(!target) treeroot = root;
}
void find(int x){
if(!treeroot) return;
int cur = treeroot;
while(node[cur].ch[x > node[cur].val] && node[cur].val != x){
cur = node[cur].ch[x > node[cur].val];
}
splay(cur);
}
int pre(int x){
find(x);
if(node[treeroot].val < x) return treeroot;
if(!node[treeroot].ch[]) return -;
int cur = node[treeroot].ch[];
while(node[cur].ch[]){
cur = node[cur].ch[];
}
return cur;
}
int succ(int x){
find(x);
if(node[treeroot].val > x) return treeroot;
if(!node[treeroot].ch[]) return -;
int cur = node[treeroot].ch[];
while(node[cur].ch[]){
cur = node[cur].ch[];
}
return cur;
}
public:
void clear(){
sign = ;
insert(INF);
insert(-INF);
allSize = ;
}
void insert(T x){
allSize ++;
int cur = treeroot, preroot = ;
while(cur && node[cur].val != x){
preroot = cur;
cur = node[cur].ch[x > node[cur].val];
}
if(cur){
node[cur].cnt ++;
}else{
if(freeMemory.empty())
cur = ++ sign;
else{
cur = freeMemory.front();
freeMemory.pop();
}
if(preroot) node[preroot].ch[x > node[preroot].val] = cur;
node[cur].val = x;
node[cur].cnt = ;
node[cur].ch[] = node[cur].ch[] = ;
node[cur].size = ;
node[cur].parent = preroot;
}
splay(cur);
}
int rank(T x){
find(x);
return node[node[treeroot].ch[]].size;
}
T preAns(T x){
return node[pre(x)].val;
}
T succAns(T x){
return node[succ(x)].val;
}
T kth(int k){
k ++;
int cur = treeroot;
while(){
if(node[cur].ch[] && k <= node[node[cur].ch[]].size){
cur = node[cur].ch[];
}else if(k > node[node[cur].ch[]].size + node[cur].cnt){
k -= node[node[cur].ch[]].size + node[cur].cnt;
cur = node[cur].ch[];
}else{
return node[cur].val;
}
}
}
void remove(T x){
allSize --;
int last = pre(x), next = succ(x);
splay(last), splay(next, last);
int del = node[next].ch[];
if(node[del].cnt > ){
node[del].cnt --;
splay(del);
}else{
freeMemory.push(node[next].ch[]);
node[next].ch[] = ;
}
}
T top(T x){
find(x);
return node[treeroot].val;
}
int getAllSize(){
return allSize;
}
}; Splay<ll> splay; int main(){
int n;
ll ans = ;
bool type = ;
scanf("%d", &n);
splay.clear();
while(n --){
int a;
ll b;
scanf("%d%lld", &a, &b);
if(a){
if(type || splay.getAllSize() == ){
splay.insert(b);
type = ;
}
else{
ll pre = splay.preAns(b), mid = splay.top(b), succ = splay.succAns(b);
ll choose;
if(abs(pre - b) <= abs(mid - b)){
choose = pre;
}else{
choose = mid;
}
if(abs(choose - b) > abs(succ - b)){
choose = succ;
}
ans = (ans + abs(choose - b)) % MOD;
splay.remove(choose);
}
}else{
if(!type || splay.getAllSize() == ){
splay.insert(b);
type = ;
}
else{
ll pre = splay.preAns(b), mid = splay.top(b), succ = splay.succAns(b);
ll choose;
if(abs(pre - b) <= abs(mid - b)){
choose = pre;
}else{
choose = mid;
}
if(abs(choose - b) > abs(succ - b)){
choose = succ;
}
ans = (ans + abs(choose - b)) % MOD;
splay.remove(choose);
}
}
}
printf("%lld\n", ans);
return ;
}
fjutacm 2492 宠物收养所 : Splay 模板 O(nlogn)的更多相关文章
- BZOJ 1208 [HNOI2004]宠物收养所 | SPlay模板题
题目: 洛谷也能评 题解: 记录一下当前树维护是宠物还是人,用Splay维护插入和删除. 对于任何一次询问操作都求一下value的前驱和后继(这里前驱和后继是可以和value相等的),比较哪个差值绝对 ...
- HNOI2004宠物收养所(splay维护二叉搜索树模板题)
描述 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...
- 【BZOJ1208】[HNOI2004]宠物收养所 Splay
还是模板题,两颗splay,找点删即可. #include <iostream> #include <cstdio> #include <cstdlib> #def ...
- [bzoj1208][HNOI2004]宠物收养所——splay
题目大意 Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发 ...
- 【BZOJ-1208】宠物收养所 Splay
1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6638 Solved: 2601[Submit][Sta ...
- BZOJ 1208 宠物收养所 | 平衡树模板题
BZOJ 1208 宠物收养所 我犯过的错误:删除一个节点后没有update新的根节点,导致size错了! #include <cstdio> #include <cmath> ...
- Bzoj 1208: [HNOI2004]宠物收养所(splay)
1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec Memory Limit: 162 MB Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收 ...
- bzoj 1208 宠物收养所--splay
这个题也是单点维护,不管来的是人还是狗,只要num=0就插入,否则就删除. // File Name: ACM/bzoj/1208.cpp // Author: Zlbing // Created T ...
- BZOJ1208 [HNOI2004]宠物收养所 splay
原文链接http://www.cnblogs.com/zhouzhendong/p/8085803.html 题目传送门 - BZOJ1208 题意概括 有两种数,依次加入. 规则为下: 如果当前剩余 ...
随机推荐
- rest-framework框架——APIView和序列化组件
一.快速实例 Quickstart http://www.cnblogs.com/yuanchenqi/articles/8719520.html restful协议 ---- 一切皆是资源,操作只是 ...
- Windows 10:开机显示C:\WINDOWS\system32\config\systemprofile\Desktop不可用 的解决方法
今晨起来开机,开完机一看,弹出啦一个框框上面写着“C:\WINDOWS\system32\config\systemprofile\Desktop不可用...” 当我点击了确定之后,发现屏幕一片黑,只 ...
- html5 填表 表单 form label input button legend fieldset
<form>本身没有什么意义, 但是某些依赖form的标签元素一旦没有了form就不能生效. 所以form是提供一个定义环境给form的插件元素去生效的. 1.method 属性pos ...
- Centos6配置samba服务器并批量添加用户和文件夹
一.需求 局域网内有若干用户,所有用户访问一个共享目录 每个用户在共享目录里有自己的文件夹 每个用户都可以读取其他人的文件夹 每个用户只能对自己的文件夹有写入权限 所有用户都属于filesgroup组 ...
- Web安全入门笔记-XSS
windows 10 360浏览器 0x00.概述 1.什么是 XSS Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击.攻击者通过在目标网站上注入恶意脚本,使 ...
- 任务四:CSS定位和居中问题
任务目标 实践HTML/CSS布局方式 深入了解position等CSS属性 任务描述 实现如 示例图(点击打开) 的效果 灰色元素水平垂直居中,有两个四分之一圆位于其左上角和右下角. 任务注意事项 ...
- 新发布 | Azure镜像市场正式上线
由世纪互联运营的 Azure 镜像市场于2016年9月21日正式落地中国市场,在客户和软件开发商间搭建起了一站式门户.来自全球和本地领先软件开发商并基于 Azure 的云应用.云服务和解决方案在门户中 ...
- WIN7系统程序放在中文文件夹打开报错及界面汉字变乱码
今天发现在一个服务商提供的设备的WIN7系统里,一个稳定运行的程序打开时报错,且界面汉字变乱码. 经测试发现程序放在英文名称的文件夹中可以正常打开,但界面上的汉字仍为乱码. 后检查“控制面板“--”区 ...
- kahadb设计
Kahadb设计思想 简介 hakadb是activemq的持久化数据库,作为消息队列的存储,每个消息有一个消息ID,提供了对消息的快速的查找,更新,以及消息的事物支持,以及意外磬机之后的恢复.丰 ...
- Visual Stuio 2010 常用快捷及操作
1.如果你想复制一行代码(超级长,鼠标拖老久的),只需要在这行的空白处 CTRL+C 同理,剪贴一行 CTRL+X 删除一行 CTRL+L 2.显示方法里的参数,以前每次都是手动删括号. CTRL+S ...