题解

本题的解法是丰富多彩的!

线段树做法是极好的

代码非常之少

一个很显然的想法是维护 \(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提高组正式赛】列队的更多相关文章

  1. [jzoj]5478.【NOIP2017提高组正式赛】列队

    Link https://jzoj.net/senior/#main/show/5478 Description Sylvia 是一个热爱学习的女孩子.       前段时间,Sylvia 参加了学校 ...

  2. 【NOIP2017 提高组正式赛】列队 题解

    题目大意 有一个 \(n\times m\) 的方阵,每次有 \((x,y)\) 离开,离开后有两个命令 向左看齐.这时第一列保持不动,所有学生向左填补空缺.这条指令之后,空位在第 \(x\) 行第 ...

  3. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  4. NOIP2017提高组 模拟赛13(总结)

    NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...

  5. NOIP2017提高组模拟赛 10 (总结)

    NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...

  6. NOIP2017提高组模拟赛 8(总结)

    NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...

  7. NOIP2017提高组模拟赛 9 (总结)

    NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...

  8. NOIP2017提高组模拟赛 7(总结)

    NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...

  9. NOIP2017提高组模拟赛5 (总结)

    NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...

  10. NOIP2017提高组模拟赛4 (总结)

    NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...

随机推荐

  1. goioc:一个使用 Go 写的简易的 ioc 框架

    目录 goioc 介绍 快速上手 接口介绍 使用 goioc 如何使用 生命周期 实例化 获取对象 结构体字段依赖注入 Dispose 接口 反射形式使用 goioc 如何使用 接口.结构体.结构体指 ...

  2. json与字符串的互转

    在spring框架中当ajax请求需要返回json数据时,我们只需要在@RequestMapping后面加上@ResponseBody,即可为我们返回想要的json. 下面我们讲解json与字符串的互 ...

  3. jmeter 从多个数中随机取一个值的方法

    问题描述:使用jmeter进行接口测试时,遇到枚举值(如:10代表闲置.15代表使用中.20代表维修等)我们需要随机取一个类型传到接口中. 解决思路:通过函数助手查找随机函数,找到__chooseRa ...

  4. 批量将多个相同Excel表格内容合并到一个Excel表格的sheet工作簿当中。

    Sub Books2Sheets()Dim fd As FileDialog Set fd = Application.FileDialog(msoFileDialogFilePicker) Dim ...

  5. 【每日一题】【递归实现、自下而上、优化】-2022年1月12日-NC68 跳台阶

    描述一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果). 数据范围:0 \leq n \leq 400≤n≤40要求:时间复杂度: ...

  6. 什么是NineData?突然就火了

    NineData 是集成了 SQL 开发.数据复制.数据备份.数据对比多个模块的云服务,支持混合云(自建库+云数据库的业务架构)和多云(多个不同云厂商数据库组成的业务架构)架构下的企业数据管理,大幅降 ...

  7. python基础语法&数据类型&运算符

    1.标识符 # -*- coding:utf-8 -*- # @Time :2021/1/16 10:28 # @Author :QAbujiaban # @Email :wbxztoo@163.co ...

  8. django 之swagger配置与生成接口文档

    swagger好处不多说,直接上配置步骤 1.安装swagger pip install django-rest-swagger 2.将swagger配置到setting.py文件中 3.在主url. ...

  9. JavaScript:对象:如何去遍历输出一个对象的属性?语句for-in

    使用for-in的for循环语句,可以去遍历一个对象的属性,这类似于Java的增强for循环: 但是注意,这并不能遍历对象的所有属性,有些隐藏的属性,是无法遍历出来的,虽然我们可以通过控制台去查看这些 ...

  10. JavaScript:代码应该编写在哪里?

    我们可以将JS的代码,编写在三个地方. 但是无论编写在哪里,最后它都会嵌入进网页代码中,被浏览器执行. 编写在script标签中 我们可以直接在HTML的script标签中,编写大段JS代码. 编写在 ...