【noip2017】【Luogu3960】列队 线段树
题目描述
Sylvia
是一个热爱学习的女♂孩子。
前段时间,Sylvia
参加了学校的军训。众所周知,军训的时候需要站方阵。
Sylvia 所在的方阵中有 n \times mn×m 名学生,方阵的行数为 nn ,列数为 mm 。
为了便于管理,教官在训练开始时,按照从前到后,从左到右的顺序给方阵中 的学生从 1 到 n \times mn×m 编上了号码(参见后面的样例)。即:初始时,第 ii 行第 jj 列 的学生的编号是 (i-1)\times m + j(i−1)×m+j 。
然而在练习方阵的时候,经常会有学生因为各种各样的事情需要离队。在一天 中,一共发生了 qq 件这样的离队事件。每一次离队事件可以用数对 (x,y) (1 \le x \le n, 1 \le y \le m)(x,y)(1≤x≤n,1≤y≤m) 描述,表示第 xx 行第 yy 列的学生离队。
在有学生离队后,队伍中出现了一个空位。为了队伍的整齐,教官会依次下达 这样的两条指令:
- 向左看齐。这时第一列保持不动,所有学生向左填补空缺。不难发现在这条 指令之后,空位在第 xx 行第 mm列。
- 向前看齐。这时第一行保持不动,所有学生向前填补空缺。不难发现在这条 指令之后,空位在第 nn 行第 mm列。
教官规定不能有两个或更多学生同时离队。即在前一个离队的学生归队之后, 下一个学生才能离队。因此在每一个离队的学生要归队时,队伍中有且仅有第 nn 行 第 mm 列一个空位,这时这个学生会自然地填补到这个位置。
因为站方阵真的很无聊,所以 Sylvia
想要计算每一次离队事件中,离队的同学 的编号是多少。
注意:每一个同学的编号不会随着离队事件的发生而改变,在发生离队事件后 方阵中同学的编号可能是乱序的。
输入输出格式
输入格式:
输入共 q+1q+1 行。
第 1 行包含 3 个用空格分隔的正整数 n, m, qn,m,q ,表示方阵大小是 nn 行 mm 列,一共发 生了 qq 次事件。
接下来 qq 行按照事件发生顺序描述了 qq 件事件。每一行是两个整数 x, yx,y ,用一个空 格分隔,表示这个离队事件中离队的学生当时排在第 xx 行第 yy 列。
输出格式:
按照事件输入的顺序,每一个事件输出一行一个整数,表示这个离队事件中离队学 生的编号。
输入输出样例
输入样例#1:
2 2 3
1 1
2 2
1 2
输出样例#1:
1
1
4
说明
【输入输出样例 1 说明】
列队的过程如上图所示,每一行描述了一个事件。 在第一个事件中,编号为 1 的同学离队,这时空位在第一行第一列。接着所有同学 向左标齐,这时编号为 2 的同学向左移动一步,空位移动到第一行第二列。然后所有同 学向上标齐,这时编号为 4 的同学向上一步,这时空位移动到第二行第二列。最后编号 为 1 的同学返回填补到空位中。
【数据规模与约定】
数据保证每一个事件满足 \(1 \le x \le n,1 \le y \le m1≤x≤n,1≤y≤m\)
前言
noip2017的时候我连线段树都不会,树状数组也只会板子,而且当时因为肛T2时间太多连50分都没写,30分就跑路了。现在回来看这个题,真的是一言难尽啊。
算法1
对于前50%的数据,我们取出所有询问用到的行和最后一列进行暴力模拟即可。
期望得分:50
算法2
对于11-16测试点,我们开1/2棵线段树,维护每个区间实际存在的数字个数,这样就可以利用区间长度-sum[x]的方法找到区间的第k个元素,同时我们维护1/2个vector,表示添加到末尾的数字,如果查找到的pos是在实际范围以内,那么直接按照pos计算,否则我们在vector中按照下标查找,之后再更新vector和线段树即可。
注意:线段树维护的是1~n+q/m+q的区间,所以空间记得开大一倍。
算法3
对每一行和最后一列维护n+1棵线段树和n+1个vector,由于动态开点我们的内存能够控制在\(nlogn\)的级别,vector中的元素在\(2q\)级别,不会超出内存限制,剩下的就按照算法2进行就行了,注意如果\(y=m\),就不用对第x行的线段树进行操作了,否则我们就先在第x行找到答案,然后在第n+1棵线段树中找到第x个元素并添加到x中,然后把ans添加到n+1中。
算法3代码
其实这道题代码还是很好写的,35行,不到1K的长度。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,q,x,y,pos,tot,lim,rt[300005],ls[12000005],rs[12000005],sm[12000005];vector<ll>v[300005];
int que(int x,int l,int r,int v)
{
if(l==r) return l;
int mid=(l+r)>>1,tmp=mid-l+1-sm[ls[x]];
if(v<=tmp) return que(ls[x],l,mid,v);
return que(rs[x],mid+1,r,v-tmp);
}
void upd(int &x,int l,int r,int p)
{
if(!x) x=++tot;sm[x]++;
if(l==r) return;int mid=(l+r)>>1;
if(p<=mid) upd(ls[x],l,mid,p);
else upd(rs[x],mid+1,r,p);
}
ll wk1(int x,ll y)
{
pos=que(rt[n+1],1,lim,x);upd(rt[n+1],1,lim,pos);
ll ans=pos<=n?1ll*pos*m:v[n+1][pos-n-1];
return v[n+1].push_back(y?y:ans),ans;
}
ll wk2(int x,int y)
{
pos=que(rt[x],1,lim,y);upd(rt[x],1,lim,pos);
ll ans=pos<m?1ll*(x-1)*m+pos:v[x][pos-m];
return v[x].push_back(wk1(x,ans)),ans;
}
int main()
{
scanf("%d%d%d",&n,&m,&q);lim=max(n,m)+q;
for(;q--;printf("%lld\n",y==m?wk1(x,0):wk2(x,y))) scanf("%d%d",&x,&y);
}
【noip2017】【Luogu3960】列队 线段树的更多相关文章
- [NOIP2017]列队(线段树/裂点splay)
考虑n=1的做法,就是支持: 1.在线删一个数 2.在结尾加一个数 3.查询序列的第y个数 用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可. 对于 ...
- [NOIP2017]列队 线段树
---题面--- 题解: 之前写的splay,,,然而一直没调出来,我感觉是某个细节想错了,,然而已经重构4次代码不想再写splay了.于是今天尝试了线段树的解法. 首先因为每次出列之后的变化都是将当 ...
- Luogu P3960 列队 线段树
题面 线段树入门题. 我们考虑线段树来维护这个矩阵. 首先我们先定n+1棵线段树前n棵维护每行前m-1个同学中没有离队过的同学,还有一棵维护第m列中没有离队过的同学.再定n+1棵线段树前n棵线段树维护 ...
- NOIP2017整数 【线段树】
题目 题目背景 在人类智慧的山巅,有着一台字长为10485761048576 位(此数字与解题无关)的超级计算机,著名理论计算机科 学家P博士正用它进行各种研究.不幸的是,这天台风切断了电力系统,超级 ...
- 洛谷 P3960 [ NOIP 2017 ] 列队 —— 线段树
题目:https://www.luogu.org/problemnew/show/P3960 NOIP 题,不用很复杂的数据结构...但又参考了许多: 要求支持维护删除第 k 个和在末尾插入的数据结构 ...
- Luogu3960 NOIP2017列队(splay/线段树)
令splay中的一个点表示一段区间,需要使用其中某个点时将区间分裂即可,剩下的都是splay的基本操作了.写的非常丑陋,注意细节.感觉考场上肯定只能靠部分分苟活了.想起来去年因为各种莫名其妙的原因50 ...
- NOIP2017 列队 题解报告【56行线段树】
题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...
- NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/9265380.html 题目传送门 - 洛谷P3960 题目传送门 - LOJ#2319 题目传送门 - Vij ...
- 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay
正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...
随机推荐
- vs中的强大的代码段管理
vs中的代码段管理可以实现大段固定文本的快捷输入,方法: 首先编写.snippet文件如: <?xml version="1.0" encoding="utf-8& ...
- 【整理】Android中的gravity和layout_gravity区别
[背景] 在Android中,想要设置个按钮的水平对齐,都累死了: [已解决]ADT中已设置TableLayout布局的情况下如何设置按钮居中对齐 所以现在有必要搞清楚,到底gravity和la ...
- java多线程编程核心技术-笔记
一.第一章 1.自定义线程类中实例变量针对其他线程有共享和不共享之分,自定义线程中的变量,如果是继承自thread类,则每个线程中的示例变量的更改,不影响其他线程2.当多个线程去访问一个局部变量是会产 ...
- 12-EasyNetQ之消息版本控制
为了能够支持消息版本控制,你需要确保这个必要的组件已配置.最简单的实现是这样的: var bus = RabbitHutch.CreateBus("host=localhost", ...
- linux单用户模式修改密码
Linux使用版本: Centos 7 救援模式: 1,在虚拟机设置里查看光驱是否开启启动,要保证设置状态里的两个选项都已选择. 2,先将Centos系统关机,然后在VMware左侧选中这台虚拟机并右 ...
- 仿函数(二、stl中常用仿函数)
提到C++ STL,首先被人想到的是它的三大组件:Containers, Iterators, Algorithms,即容器,迭代器和算法.容器为用户提供了常用的数据结构,算法大多是独立于容器的常用的 ...
- map两种插入方法解析(insert() 与 下标[]操作)
insert 含义是: 如果key存在,则插入失败,如果key不存在,就创建这个key-value. 实例: map.insert((key, value)) 利用下标操作的含义是: 如果这个key存 ...
- mfs权威指南
1. 我在性能测试中间遇到些问题,因为我时间有限,所以希望大家一起来测试解决,群策群力.有什么问题请大家及时指出来,因为我也处在一个不断摸索的阶段. 2. mfs不多做介绍,具体细节请参考本版mfs实 ...
- struts2 与 spring 整合
1. 首先把所有jar包导入工程 2.在struts2的核心配置文件(在src文件目录下)中添加如下配置: <!-- 将Struts的对象交给Spring管理 所以需要导入Spring和Stru ...
- SQL Server 本地时间和UTC时间的相互转换
SET @UTCDate = DATEADD(hour, DATEDIFF(hour,GETDATE(),GETUTCDATE()), @LocalDate) SET @LocalDate2 = DA ...