题解

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

线段树做法是极好的

代码非常之少

一个很显然的想法是维护 \(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. 在Linux配置git

    生成ssh ssh-keygen -t rsa 可以不设置密码,一路回车就行,会在 ~/.ssh/下生成两个ssh key: ssh-add ~/.ssh/id_rsa.pub 这一步是使用刚才生成那 ...

  2. win7使用onedrive右键托盘图标中文不显示问题

    前言 win7 用的 onedrive不能在微软官网下载,用不了,所以需要下载 win7可以使用的版本. onedrive_for_win7.exe 解决问题 重启电脑解决 其他 我看贴吧说是文本放大 ...

  3. linux sublime-text ctrl+shift+b 快捷键失效问题解决

    解决办法 由于fcitx拦截了这个ctrl+shift+b 这个快捷键,所以取消即可 点击全局配置里面高级选项,然后找到ctrl+shift+b这个快捷键,点击后,按esc就可以将快捷键设置为空,不过 ...

  4. SSH(五)spring整合hibernate

    一.创建hibernate实体映射文件. 在实体所在包创建映射文件product.hbm.xml,引入hibernate的映射约束.(该约束位于hibernate3.jar里面hibernate-ma ...

  5. PHP日期加减计算

    PHP 标准的日期格式 date("Y-m-d H:i:s"); PHP 简单的日期加减计算 <?php date_default_timezone_set('PRC'); ...

  6. 【Shell案例】【打印指定行用sed、for循环、head和tail配合使用】4、输出第5行的内容

    描述写一个 bash脚本以输出一个文本文件 nowcoder.txt 中第5行的内容. 示例:假设 nowcoder.txt 内容如下:welcometonowcoderthisisshellcode ...

  7. 【SQL基础】【关键字大写】条件查询:比较、不等于、IN、为空、BETWEEN

    〇.概述 1.内容介绍 条件查询:比较.不等于.IN.为空.BETWEEN 2.建表语句 drop table if exists user_profile; CREATE TABLE `user_p ...

  8. 使用pandas处理数据和matplotlib生成可视化图表

    一.缘由 上一篇输入关键词"口红",将淘宝中的的相关商品信息全部爬取了下拉,并且以CSV的文件格式储存.我们拿到数据之后,那么就需要对数据进行处理.只是将爬取到的数据以更直观的方式 ...

  9. UVA 673 Paretheses Balance

    原题Vjudge 题目大意 怼给你一堆括号,判断是否合法 有三条规则 (1)空串合法 (2)如果\(A和B\)都合法,则\(AB\)合法(例如:\(()和[]\)都合法,则\(()[]\)合法) (3 ...

  10. 主题 1 The Shell

    主题 1 The Shell 课程概览与 shell · the missing semester of your cs education (missing-semester-cn.github.i ...