考虑转化题意:

设这次操作删掉点\((x, y)\)

对于每一次向左看齐:在第x行删除\((x, y)\),并将y以后的点全部前移一位

对于每一次向前看齐:x以后的点全部上移一位,并在最后一列插入\((x, y)\)

这些操作都可以用\(Splay\)解决:

我们开\(N+1\)棵\(Splay\),1到N棵表示的是第i行,[1,m-1]的位置,第\(N+1\)棵表示最后一列的位置

这样我们可以把所有的点都扔进一棵\(Splay\)里面

题意有一次转化成:

设这次操作删掉点\((x, y)\)

对于每一次向左看齐:在第x棵\(Splay\)删除排名为\(y\)的节点,再将N+1棵\(Splay\)内的排名为\(x\)的节点删除并插入到第x棵\(Splay\)中

对于每一次向前看齐:在第\(N+1\)棵\(Splay\)中插入\((x, y)\)

但是这样的空间复杂度开销很大(\(NM\)),显然不能过这道题

发现询问次数不多,而每一次询问需要动的点也很少,所以每一棵\(Splay\)里面存的节点变成了一个区间

每一次删除把区间分成3份:l ~ pos - 1, pos ~ pos, pos + 1 ~ r

删掉中间一份即可

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define debug printf("Now is Line : %d\n",__LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define LL long long
il int read() {
re int x = 0, f = 1; re char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define maxn 10000005
namespace splay {
int fa[maxn], ch[2][maxn], rt[maxn], tot;
#define pushup(x) size[x] = size[ch[0][x]] + size[ch[1][x]] + val[x].size
#define get_fa(x) (ch[1][fa[x]] == x)
LL size[maxn];
struct node {
LL l, r, size;
}val[maxn];
il void rotate(int x) {
int y = fa[x], z = fa[y], w = get_fa(x), k = get_fa(y);
ch[k][z] = x, fa[x] = z, ch[w][y] = ch[w ^ 1][x];
fa[ch[w ^ 1][x]] = y, ch[w ^ 1][x] = y, fa[y] = x;
pushup(y), pushup(x);
}
il void Splay(int k, int x, int want) {
while(fa[x] != want) {
int y = fa[x];
if(fa[y] != want) rotate(get_fa(x) == get_fa(y) ? y : x);
rotate(x);
}
if(!want) rt[k] = x;
}
il void insert(int k, LL x) {
int u = rt[k], f = 0;
while(u) f = u, u = ch[1][u];
u = ++ tot;
size[u] = 1, fa[u] = f, val[u] = (node){x, x, 1}, ch[1][f] = u, Splay(k, u, 0);
}
il LL spilt(int p, int k, LL x) {
LL s = val[k].l, t = val[k].r;
if(s != x && t != x) {
if(s + 1 < t) {
int u = ++ tot;
val[u].l = x + 1, val[u].r = val[k].r, val[u].size = (val[u].r - val[u].l + 1);
val[k].r = x - 1, val[k].size = (val[k].r - val[k].l + 1);
ch[1][u] = ch[1][k], ch[1][k] = u, fa[u] = k, Splay(p, u, 0);
}
else ++ val[k].l, -- val[k].size, Splay(p, k, 0);
}
else {
if(s == x) ++ val[k].l;
else -- val[k].r;
-- val[k].size, Splay(p, k, 0);
}
return x;
}
il LL K_th(int k, int x) {
int u = rt[k];
while(1) {
if(size[ch[0][u]] >= x) u = ch[0][u];
else if(size[ch[0][u]] + val[u].size < x) x -= size[ch[0][u]] + val[u].size, u = ch[1][u];
else return spilt(k, u, x - size[ch[0][u]] + val[u].l - 1);
}
}
}
using namespace splay;
int n, m, q;
signed main() {
n = read(), m = read(), q = read();
rep(i, 1, n) {
rt[i] = ++ tot, val[tot].size = m - 1;
val[tot].l = 1ll * (i - 1ll) * m + 1ll, val[tot].r = 1ll * i * m - 1ll;
}
rep(i, 1, n) insert(0, 1ll * i * m);
while(q --) {
int x = read(), y = read();
if(y == m) {
LL u = K_th(0, x);
printf("%lld\n", u), insert(0, u);
}
else {
LL u = K_th(x, y);
printf("%lld\n", u), insert(x, K_th(0, x)), insert(0, u);
}
}
return 0;
}

[NOIP2017] 列队(平衡树)的更多相关文章

  1. NOIP2017 列队——平衡树

    平衡树蒟蒻,敲了半天. 其实思路很简单,就是把许多个人合并成一个区间.必要的时候再拆开.(是不是和这个题的动态开点线段树有异曲同工之妙?) 每次操作最多多出来6个点. 理论上时间复杂度是nlogn,空 ...

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

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

  3. [NOIP2017]列队 离线+SBT

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

  4. 题解[NOIP2017] 列队

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

  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. IOC之Unity的使用详解

    原文链接:https://www.cnblogs.com/hua66/p/9670639.html Unity作为Microsoft推出IOC容器,其功能是非常丰富的,其中需要注意的地方也不少.以下是 ...

  2. 初学pyhon的几个练习小程序

    一.概述 此程序示例为博主根据路飞学城的python的作业而写的(博主也是python初学者,仅花了99元报了路飞学城的python入门14天集中营3期网络课堂班),此程序非常适合python初学者拿 ...

  3. 利用Redis keyspace notification(键空间通知)实现过期提醒

    一.序言: 本文所说的定时任务或者说计划任务并不是很多人想象中的那样,比如说每天凌晨三点自动运行起来跑一个脚本.这种都已经烂大街了,随便一个 Crontab 就能搞定了. 这里所说的定时任务可以说是计 ...

  4. 观察者模式与.Net Framework中的委托与事件

    本文文字内容均选自<大话设计模式>一书. 解释:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够 ...

  5. appium+python搭建自动化测试框架_TestAPP框架(三)

    Pycharm 创建 Project,搭建 APPTEST框架如下图:   1.框架功能 业务功能的封装 测试用例封装 测试包管理 截图处理 断言处理 日志获取 测试报告生成 数据驱动 数据配置 2. ...

  6. Go语言打造以太坊智能合约测试框架(level2)

    传送门: 柏链项目学院 第二课 智能合约自动化编译 前期内容回顾 之前我们的介绍的是如何通过solc编译智能合约,并且调用智能合约,本节我们继续实践,将智能合约的代码自动化编译以及abi文件生成搞定. ...

  7. go语言模版编程

    传送门: 柏链项目学院 go语言与模版编程 什么是模版编程 模板是将一个事物的结构规律予以固定化.标准化的成果,它体现的是结构形式的标准化.对于我们程序员来说,更直白的理解是:对于要输出的内容,个人位 ...

  8. html元素禁用disable or enable

    场景说明 ajax提交数据,防止收到服务端相应前用户重复点击. 1.用户点击按钮,禁用当前按钮,发起ajax请求. 2.收到ajax请求,还原当前按钮. html解决方案 参考地址:http://ww ...

  9. php 7.1 新特性解析

    php 7.1 新特性解析 返回值和传入参数可以指定为 null <?php function testReturn(): ?string { return 'elePHPant'; } var ...

  10. Fiddler分享

    链接:https://pan.baidu.com/s/162YmGb7-aUZ6xDf8eRfgpw  密码:j6er