【NOIP2017提高组正式赛】列队
题解
本题的解法是丰富多彩的!
线段树做法是极好的
代码非常之少
一个很显然的想法是维护 \(n+1\) 颗线段树
那要怎么维护才能不爆空间呢?
我们发现尽管 \(n \times m\) 那么大
但 \(q\) 相比 \(n \times m\) 小得多
也就是说变动的点比较少
于是我们抓住这点
考虑只记录变动的点
行的线段树维护 \([1,m-1]\) 位置的信息
列的线段树维护 \([1,n]\) 的位置的信息
那我一颗线段树就记录那些点不在原来位置了
也就是说一颗线段树长为 \(\max(n,m)+q\) (为什么?待会再解释)
每一位只为 \(0\) 或 \(1\) 表示 没变或变了
\(1\) 表示变了是因为没变的太多无法记录,那就记变的吧
这样线段树动态开点空间就可以接受了
然后变动的点我们考虑它后来的位置
依题知它会到最后一列的末端,然后最后一列它所在的行的点会到它所在行的线段是的末端
我们无法向平衡树一样动态移动(插入,删除)点,但题目只需插入到末端
所以我们预留空间把插入的点放到末端,然后它原来位置标记为 \(1\),表示此处无点
对于查询,我们知道为第 \(x(x<=n)\) 颗线段树的 \(y\) 位置的点的编号为 \((x-1) \times m+y\)
但他不一定在原队列 \(y\) 位置
因为前面有些点为 \(1\) 空置,一个区间长度减去区间 \(1\) 的个数才是区间有的数
所以我们只要查询排名为 \(y\) 的位置的编号,记为 \(z\)
那么在询问中,当 \(z<m\) 时,它的编号为 \((x-1) \times m+z\)
当 \(z >= m\) 时说明前面有空位,有点移动到后面了
我们用 \(n+1\) 个 \(vector\) 储存每个线段树依次移动到后面的点,输出 \(S[x][z-m]\) 即可
列同理
\(Code\)
#include<cstdio>
#include<vector>
#include<iostream>
#define LL long long
using namespace std;
const int N = 3e5 + 5, M = 6e6 + 5;
int n, m, q, sum[M], ls[M], rs[M], rt[N], Len, size;
vector<LL> S[N];
void update(int &p, int l, int r, int x)
{
if (!p) p = ++size;
++sum[p];
if (l == r) return;
int mid = (l + r) >> 1;
if (x <= mid) update(ls[p], l, mid, x);
else update(rs[p], mid + 1, r, x);
}
int query(int p, int l, int r, int k)
{
if (l == r) return l;
int mid = (l + r) >> 1, s = mid - l + 1 - sum[ls[p]];
if (k <= s) return query(ls[p], l, mid, k);
return query(rs[p], mid + 1, r, k - s);
}
inline LL move_forward(int x)
{
int p = query(rt[n + 1], 1, Len, x);
update(rt[n + 1], 1, Len, p);
return (p <= n ? (1LL * p * m) : (S[n + 1][p - n - 1]));
}
inline LL move_left(int x, int y)
{
int p = query(rt[x], 1, Len, y);
update(rt[x], 1, Len, p);
return (p < m ? (1LL * (x - 1) * m + p) : (S[x][p - m]));
}
int main()
{
freopen("phalanx.in", "r", stdin);
freopen("phalanx.out", "w", stdout);
scanf("%d%d%d", &n, &m, &q);
Len = max(n, m) + q;
for(int x, y; q; --q)
{
scanf("%d%d", &x, &y);
LL z;
if (y == m) z = move_forward(x), printf("%lld\n", z), S[n + 1].push_back(z);
else z = move_left(x, y), printf("%lld\n", z), S[n + 1].push_back(z),
z = move_forward(x), S[x].push_back(z);
}
}
【NOIP2017提高组正式赛】列队的更多相关文章
- [jzoj]5478.【NOIP2017提高组正式赛】列队
Link https://jzoj.net/senior/#main/show/5478 Description Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校 ...
- 【NOIP2017 提高组正式赛】列队 题解
题目大意 有一个 \(n\times m\) 的方阵,每次有 \((x,y)\) 离开,离开后有两个命令 向左看齐.这时第一列保持不动,所有学生向左填补空缺.这条指令之后,空位在第 \(x\) 行第 ...
- NOIP2017提高组 模拟赛15(总结)
NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...
- NOIP2017提高组 模拟赛13(总结)
NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...
- NOIP2017提高组模拟赛 10 (总结)
NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...
- NOIP2017提高组模拟赛 8(总结)
NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...
- NOIP2017提高组模拟赛 9 (总结)
NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...
- NOIP2017提高组模拟赛 7(总结)
NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...
- NOIP2017提高组模拟赛5 (总结)
NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...
- NOIP2017提高组模拟赛4 (总结)
NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...
随机推荐
- 【每日一题】【DFS和回溯的区别】【BFS】104. 二叉树的最大深度-211227/220218
给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,null,15,7], ...
- SLM6500电磁干扰认证设计PCB
SLM6500 是一款面向5V交充适配器的2A离子电池充电器.它是采用1.5MHz固定频率的步降压型转换器,利用芯片内部的功率晶体管电池进行涓流.恒流和恒压充电.充电电流可用外部电阻编程设定,持续充电 ...
- 基于opencv实现简单人脸检测
作用:在视频中自动检测出人脸 使用内容:灰度转换,分类器,矩形框选,圆形框选,摄像头读取及释放 代码逻辑: 先读取摄像头后, 对摄像头拍摄到的图片进行逐帧分析, 并对图像进行灰度转换后使用类选择器识别 ...
- 彻底理解Python中的闭包和装饰器(上)
什么是闭包 闭包(Closure)其实并不是Python独有的特性,很多语言都有对闭包的支持.(当然,因为Python是笔者除C/C++之外学习的第二门语言,所以也是第一次遇到闭包.)简而言之,闭包实 ...
- 视图 触发器 事务 MVCC 存储过程 MySQL函数 MySQL流程控制 索引的数据结构 索引失效 慢查询优化explain 数据库设计三范式
目录 视图 create view ... as 触发器 简介 创建触发器的语法 create trigger 触发器命名有一定的规律 临时修改SQL语句的结束符 delimiter 触发器的实际运用 ...
- Triple 协议支持 Java 异常回传的设计与实现
作者:Apache Dubbo Contributor 陈景明 背景 在一些业务场景, 往往需要自定义异常来满足特定的业务, 主流用法是在catch里抛出异常, 例如: public void dea ...
- [python]《Python编程快速上手:让繁琐工作自动化》学习笔记7
1. 用GUI 自动化控制键盘和鼠标第18章 (代码下载) pyautogui模块可以向Windows.OS X 和Linux 发送虚拟按键和鼠标点击.根据使用的操作系统,在安装pyautogui之前 ...
- JAVA中使用最广泛的本地缓存?Ehcache的自信从何而来2 —— Ehcache的各种项目集成与使用初体验
大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 在上一篇文章<JAVA中使用最广 ...
- .NET6使用NLog向文件、数据库写数据
1.Nuget 引入 NLog NLog.Web.AspNetCore NLog.Database(写入数据库使用) 2.创建nlog.config 注意数据库连接字符串需要配置TrustServer ...
- P8844 [传智杯 #4 初赛] 小卡与落叶
简要题意 给出一个 \(n\) 个节点的以 \(1\) 为根的树,每一个节点 \(i\) 带权 \(w_i\),初始时所有节点的权均为 \(0\).有 \(m\) 个操作,支持以下操作: 1 x,对于 ...