/**
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)的更多相关文章

  1. BZOJ 1208 [HNOI2004]宠物收养所 | SPlay模板题

    题目: 洛谷也能评 题解: 记录一下当前树维护是宠物还是人,用Splay维护插入和删除. 对于任何一次询问操作都求一下value的前驱和后继(这里前驱和后继是可以和value相等的),比较哪个差值绝对 ...

  2. HNOI2004宠物收养所(splay维护二叉搜索树模板题)

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

  3. 【BZOJ1208】[HNOI2004]宠物收养所 Splay

    还是模板题,两颗splay,找点删即可. #include <iostream> #include <cstdio> #include <cstdlib> #def ...

  4. [bzoj1208][HNOI2004]宠物收养所——splay

    题目大意 Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发 ...

  5. 【BZOJ-1208】宠物收养所 Splay

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6638  Solved: 2601[Submit][Sta ...

  6. BZOJ 1208 宠物收养所 | 平衡树模板题

    BZOJ 1208 宠物收养所 我犯过的错误:删除一个节点后没有update新的根节点,导致size错了! #include <cstdio> #include <cmath> ...

  7. Bzoj 1208: [HNOI2004]宠物收养所(splay)

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec Memory Limit: 162 MB Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收 ...

  8. bzoj 1208 宠物收养所--splay

    这个题也是单点维护,不管来的是人还是狗,只要num=0就插入,否则就删除. // File Name: ACM/bzoj/1208.cpp // Author: Zlbing // Created T ...

  9. BZOJ1208 [HNOI2004]宠物收养所 splay

    原文链接http://www.cnblogs.com/zhouzhendong/p/8085803.html 题目传送门 - BZOJ1208 题意概括 有两种数,依次加入. 规则为下: 如果当前剩余 ...

随机推荐

  1. 人工智能(AI)

    一.人工智能的核心——机器学习 人工智能是一个很大的圈子,但人工智能的基础是机器学习. 机器学习是什么? 其实就是人告诉机器想做什么事情,并且给它一堆数据让它模仿着去做. 机器学习需要什么? 算法.数 ...

  2. Topcoder SRM 563 Div1 500 SpellCards

    题意 [题目链接]这怎么发链接啊..... 有\(n\)张符卡排成一个队列,每张符卡有两个属性,等级\(li\)和伤害\(di\). 你可以做任意次操作,每次操作为以下二者之一: 把队首的符卡移动到队 ...

  3. 关于easyui 窗口位置的调整

    (一)easyui 默认的窗口位置 浏览器中间 (二)可直接在style里进行更改 <div id="news_dialog" class="easyui-wind ...

  4. 数据库系统异常排查之DMV(转)

    来源: http://www.cnblogs.com/fygh/archive/2012/03/12.html 数据库系统异常是DBA经常要面临的情景,一名有一定从业经验的DBA,都会有自己一套故障排 ...

  5. Azure镜像市场再下一城,中标软件入驻开启Azure国产操作系统时代

    近日,中标软件成功入驻 Azure 镜像市场,提供中标麒麟 Linux 的产品镜像服务,这样一来,中标麒麟也成为国内唯一能够在 Azure 公有云上运行的国产操作系统产品. 作为国内操作系统的领头羊, ...

  6. Java应用程序

    示例: public class HelloWorld { public static void main(String[] args) { System.out.println("Hell ...

  7. YUV数据详解

    http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html YUV格式有两大类:planar和packed.对于planar的YUV ...

  8. springMvc-入参对象

    1.修改或者添加对象 2.多添件查询时候也会遇到 springMvc能够根据属性自动的封装pojo的对象并且支持关联的对象:大致的原理是在传入后台的时候把前台的属性和对象封装成json的形式传入后台, ...

  9. 通过yum安装最新服务

    给yum添加所安装服务最新rpm源  #这里用mysql为例 # wget dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm # y ...

  10. python中的 if __name__ == “__main__”: 有什么用

    https://stackoverflow.com/questions/419163/what-does-if-name-main-do# 问题: What does if name == " ...