平衡树蒟蒻,敲了半天。

其实思路很简单,就是把许多个人合并成一个区间。必要的时候再拆开。(是不是和这个题的动态开点线段树有异曲同工之妙?)

每次操作最多多出来6个点。

理论上时间复杂度是nlogn,空间复杂度实际远远小于上界,其实4*n即可。

出错点:

1.pushup把哨兵sz变成了1:pushup要特判x!=0(比较保险)

2.fa和son的边一定要成对一起添加!!t[t[y].ch[0]=t[x].ch[0]].fa=y 压行的话不容易漏。

3.对于一列的情况,可能删除之后整个树空了。但是如果直接找的话,因为哨兵0有奇奇怪怪的左右儿子和father,所以,一路上会把0的sz变成1,并且访问到奇奇怪怪的点23333

那就特判如果没有根的话,那就直接建立即可。

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
using namespace std;
typedef long long ll;
const int N=+;
struct node{
int ch[];
int sz;
int L,R;
int fa;
ll val;
}t[N*];
int tot;
void rd(int &x){
char ch;x=;
while(!isdigit(ch=getchar()));
for(x=ch^'';isdigit(ch=getchar());x=x*+(ch^''));
}
int rt[N];
int now;
int n,m,q;
void pushup(int x){
if(x)
t[x].sz=t[t[x].ch[]].sz+t[t[x].ch[]].sz+t[x].R-t[x].L+;
}
void rotate(int x){
int y=t[x].fa,d=(t[y].ch[]==x);
t[t[y].ch[d]=t[x].ch[!d]].fa=y;
t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[]==y]=x;
t[t[x].ch[!d]=y].fa=x;
pushup(y);
}
void splay(int x,int f){
while(t[x].fa!=f){
int y=t[x].fa,z=t[y].fa;
if(z!=f){
rotate((t[y].ch[]==x)==(t[z].ch[]==y)?y:x);
}
rotate(x);
}
pushup(x);
if(f==) rt[now]=x;
}
ll get(int pos){
if(now==n+){
return (ll)pos*m;
}
return (ll)(now-)*m+pos;
}
void ins(int x,ll c){
if(x==){
++tot;
t[tot].fa=;
t[tot].val=c;
t[tot].L=t[tot].R=;
pushup(tot);
rt[now]=tot;
}
else{
while(t[x].ch[]) t[x].sz++,x=t[x].ch[]; ++tot;
t[x].ch[]=tot;
t[tot].fa=x;
t[tot].L=t[tot].R=;t[tot].val=c;
t[tot].sz=;
pushup(x);
splay(tot,);
int tmp=rt[now];
}
}
ll query(int x,int k){//and dele
int d=k-t[t[x].ch[]].sz;
if(d<=) return query(t[x].ch[],k);
else if(t[x].R-t[x].L+<d) return query(t[x].ch[],d-(t[x].R-t[x].L+));
else{//find position
ll ret=;
if(t[x].R>t[x].L){
if(d>){
++tot;
t[tot].L=t[x].L;t[tot].R=t[x].L+d-;
t[t[tot].ch[]=t[x].ch[]].fa=tot;
t[t[x].ch[]=tot].fa=x;
pushup(tot);
}
if(d<t[x].R-t[x].L+){
++tot;
t[tot].L=t[x].L+d;t[tot].R=t[x].R;
t[t[tot].ch[]=t[x].ch[]].fa=tot;
t[t[x].ch[]=tot].fa=x;
pushup(tot);
}
t[x].val=get(t[x].L+d-);
t[x].L=t[x].R=;
}else if(t[x].R){
t[x].val=get(t[x].R);
t[x].L=t[x].R=;
}
pushup(x); ret=t[x].val; splay(x,);
int son=t[x].ch[];
if(!son){
t[rt[now]=t[x].ch[]].fa=;
pushup(rt[now]);
}
else{
while(t[son].ch[]) son=t[son].ch[];
splay(son,rt[now]); t[t[son].ch[]=t[x].ch[]].fa=son;
t[son].fa=;
pushup(son);
rt[now]=son;
}
return ret;
}
}
int main(){
rd(n);rd(m);rd(q);
int x,y;
for(reg i=;i<=n;++i){
rt[i]=++tot;
t[tot].L=,t[tot].R=m-;
t[tot].sz=m-;
t[tot].fa=;
}
rt[n+]=++tot;
t[tot].L=,t[tot].R=n;
t[tot].sz=n;
while(q--){
rd(x);rd(y);
ll id=;
if(y==m) now=n+,id=query(rt[now],x);
else now=x,id=query(rt[now],y);
printf("%lld\n",id);
now=n+;
ins(rt[now],id);
if(y!=m){
now=n+;
id=query(rt[now],x);
now=x;
ins(rt[now],id);
}
}
return ;
}

NOIP2017 列队——平衡树的更多相关文章

  1. [UOJ#334][NOIP2017]列队 平衡树/线段树/树状数组

    题目链接 题意不说了,一辈子也忘不掉 解法1.平衡树 这题就是平衡树裸题,每一行开一棵维护前 \(m-1\) 个,最后一列单独维护,因为很多人没有用到,所以平衡树每个节点是一个区间(pair),分裂时 ...

  2. [NOIP2017]列队 离线+SBT

    [NOIP2017]列队 题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵 ...

  3. 题解[NOIP2017] 列队

    题解[NOIP2017] 列队 题面 解析 看到这题时感觉这个编号很难维护啊? 后来看了lzf大佬的题解才会.. 首先,考虑一个稍微暴力的做法, 维护每一行的前\(m-1\)个人和最后一列的\(n\) ...

  4. [NOIP2017] 列队(平衡树)

    考虑转化题意: 设这次操作删掉点\((x, y)\) 对于每一次向左看齐:在第x行删除\((x, y)\),并将y以后的点全部前移一位 对于每一次向前看齐:x以后的点全部上移一位,并在最后一列插入\( ...

  5. [NOIP2017]列队 (Splay)

    题目链接 NOIP2017真的是不按常理出牌: 1.数学题不在Day2T1 2.一道水题一道细节极多的模拟题一道不知道怎么形容的题(小凯的疑惑)(因为我太菜了) 3.3道大火题 当时看到列队这题是毫无 ...

  6. NOIP2017列队(phalanx)解题报告

    列队作为NOIP2017最后一道题,其实并不难,只是相对于其它题目,有点小小的工业 首先,这道题我用splay维护的,如果你不会splay,又想学一下splay,可以来这里学一学,接下来步入正题 首先 ...

  7. NOIP2017 列队 题解报告【56行线段树】

    题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...

  8. NOIP2017 列队——动态开点线段树

    Description: Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵的行数为  ...

  9. Luogu 3960 [NOIP2017] 列队 - splay|线段树

    题解 是我从来没有做过的裂点splay... 看的时候还是很懵逼的QAQ. 把最后一列的$n$个数放在一个平衡树中, 有 $n$ 个点 剩下的$n$行数, 每行都开一个平衡树,开始时每棵树中仅有$1$ ...

随机推荐

  1. Postman 高级用法指南

    Postman是一款强大的API接口测试工具,有许多不容易发现的好用的功能,下面简单介绍其中一部分功能.详细内容可以参考文档,官方还有视频教程,非常方便入手.后续本博客会持续提供一些Postman使用 ...

  2. windows环境下jmeter生成测试报告

    1.要求 jmeter需要在3.0版本以上 jdk1.7以上 需要准备脚本文件,即jmx文件 2.进入cmd界面 3.进入jmeter的bin目录 cd:\xxxx\apache-jmeter-4.0 ...

  3. 使用getid3获取音频文件信息

    今天有个需求,在上传音频文件时候自动获取音频的秒数,和大家分享一下. 首先把getid3的包下载下来 链接:https://pan.baidu.com/s/1Qmdj-I4boz9Sm9GFsON0D ...

  4. JS里点击事件判断是否 触发了节点 和给标签添加class属性

    $("#activityType").click(function(e){ if(e.target==$("#bb")[0]){ var bb=document ...

  5. [SHELL]输出目录下所有的可执行文件,批量创建用户

    #!/bin/bash IFS=: for folder in $PATH #PATH变量分隔符为: do echo $folder echo ------------------ for file ...

  6. 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档

    孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 到今天终于完成了对docx模块针对 ...

  7. python 打包

    一.下载 pip install Pyinstaller 二.使用Pyinstaller 1.使用下载安装的方式安装的Pyinstaller打包方式 将需要打包的文件放在解压得到的Pyinstalle ...

  8. 干货来袭:Redis5.0支持的新功能说明

    Redis5.0支持的新特性说明 本文内容来自华为云帮助中心 华为云DCS的Redis5.x版本继承了4.x版本的所有功能增强以及新的命令,同时还兼容开源Redis5.x版本的新增特性. Stream ...

  9. 【Python 开发】第一篇:计算机基础

    一.计算机基础 首先Python是一门编程语言 语言: 那什么是语言? 语言就是一种事物与另一种事物沟通的介质.所以说编程语言是程序员跟计算机沟通的介质. 什么是编程: 准确来说就是程序员用计算机所能 ...

  10. beego 笔记

    1.开发文档 https://beego.me/docs/intro/ 2.bee run projectname demo controller package autoscaler import ...