题目链接

题目描述

Sylvia 是一个热爱学习的女孩子。

前段时间,Sylvia 参加了学校的军训。众所周知,军训的时候需要站方阵。

Sylvia 所在的方阵中有n×mn×m名学生,方阵的行数为 nn,列数为 mm。

为了便于管理,教官在训练开始时,按照从前到后,从左到右的顺序给方阵中 的学生从 1 到 n×mn×m 编上了号码(参见后面的样例)。即:初始时,第 ii 行第 jj 列 的学生的编号是(i−1)×m+j(i−1)×m+j。

然而在练习方阵的时候,经常会有学生因为各种各样的事情需要离队。在一天 中,一共发生了 qq件这样的离队事件。每一次离队事件可以用数对(x,y)(1≤x≤n,1≤y≤m)(x,y)(1≤x≤n,1≤y≤m)描述,表示第 xx 行第 yy 列的学生离队。

在有学生离队后,队伍中出现了一个空位。为了队伍的整齐,教官会依次下达 这样的两条指令:

  1. 向左看齐。这时第一列保持不动,所有学生向左填补空缺。不难发现在这条 指令之后,空位在第 xx 行第 mm列。

  2. 向前看齐。这时第一行保持不动,所有学生向前填补空缺。不难发现在这条 指令之后,空位在第 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 列。

输出格式:

按照事件输入的顺序,每一个事件输出一行一个整数,表示这个离队事件中离队学 生的编号。

刚拿到这道题的时候,的确是无从下手的感觉,知道有这样的一道题,【SCOI2006】的动态最值,这样一道题,但是那道题是维护再一维空间上的删除并且挪动这样的一个操作,我们对于那道题只需要开线段树去维护(甚至不需要可持久化维护),维护的是size,也就是这段区间上有几个数,然后我们直接维护对应的最小值和最大值即可,线段树区间的长度就是原来的N个数的长度(因为只有N个数的说,并且还是只有删除操作)。然后一开始的时候,我们直接buildtree,并且直接赋值即可,然后在后面的找区间的时候,左区间超过L个数、右区间共有R个数,这样的(用size来维护)。

这里讲一下该怎么去维护:

我们假设左子树有X个节点,向右区间查找的时候,记得减去X,

如果ql<=X && qr>X,那么我们左右都要查;

如果ql>X && qr>X,那么我们直接查右区间;

如果ql<=X && qr<=X,我们只查左区间。

同样的,我们也可以删除。

讲了这么多与这道题没有关系的,接下来回归到正题上来。

思路:上面讲了这些,是为了开拓在可持久化线段树上的思路的,并且用到这道题就可以了。关键在于是怎么用?这道题会有这样的两种操作,一种是我们拎出来的人在第M列,那么他就不需要(操作1)向左移动了,直接向前移动即可;另一种是他不在第M列,此时我们就要考虑他要先向左移动,然后在向前对齐(向前对齐的时候,是不是就是可以看成我们挪动的是第M列的数)。

有了这些思路之后,就可以开始写了,因为这里的区间长度会比较的大,很显然,我们不能去用线段树来直接维护,那么就是需要用到可持久化线段树了,先想个办法维护一下在第M列时候的情况,因为这时候我们只需要向前看齐就可以了,那么我们是不是可以看成单链的一维空间那样子的想法(就是上面的思想了),但是这里需要补,怎么补就是个问题了,我们在这里可以开一个vector<>来存,把每个最后的值就是直接pushback就可以了。

那么,假如我们拎出去的人不是第M列的怎么办呢?假如拎出去的人的坐标是(x, y),那么我们是不是要去x这一行去找到y位的这个数,然后得到他的实际值,这时候(x, y)这个点空出来了,先要这一列的其他人都靠过来,然后再是第M列的人往前走,靠过来的做法与之前一维的时候相同,但是第M列的人向前走呢,我们可以看到M列的人,从第x位开始空出来,后面的人向前走,是不是就可以相当是第x位以后的点都向前移了一位,而查第M列的第x位不就是查其后面的数呢,然后这时候,就要把原来(x, y)上的值给赋值到M列的最后一个,也就是pushback()进去即可,同时还要把在M列x行后面的x+1行的值给塞到第x行的pushback后面去。

 #include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = ;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, , BUF_SIZE, stdin);
if(pend == p1) {
IOerror = ;
return -;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror) return;
for(x = ch - ''; (ch = nc()) >= '' && ch <= ''; x = x * + ch - '');
}
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 6e5 + ;
int N, M, Q, root[maxN], _UP, lc[ * maxN], rc[ * maxN], siz[ * maxN], tot;
vector<ll> vt[maxN];
inline void insert(int &rt, int l, int r, int k)
{
if(!rt) rt = ++tot;
siz[rt]++;
if(l == r) return;
int mid = HalF;
if(k <= mid) insert(lc[rt], l, mid, k);
else insert(rc[rt], mid + , r, k);
}
int query(int rt, int l, int r, int k)
{
if(l == r) return l;
int mid = HalF, size_L = mid - l + - siz[lc[rt]];
if(k <= size_L) return query(lc[rt], l, mid, k);
else return query(rc[rt], mid + , r, k - size_L);
}
inline ll del_M_las(int x, ll val) //如果这个人是最后那一排的话,就不需要向左看齐了
{
int pos = query(root[N + ], , _UP, x); insert(root[N + ], , _UP, pos);
ll ans = pos <= N ? (ll)pos * (ll)M : vt[N + ][pos - N - ];
vt[N + ].push_back(val ? val : ans);
return ans;
}
inline ll del_N(int x, int y)
{
int pos = query(root[x], , _UP, y); insert(root[x], , _UP, pos);
ll ans = pos < M ? (ll)(x - ) * (ll)M + pos : vt[x][pos - M];
vt[x].push_back(del_M_las(x, ans));
return ans;
}
int main()
{
tot = ;
scanf("%d%d%d", &N, &M, &Q);
//read(N); read(M); read(Q);
_UP = max(N, M) + Q;
int x, y;
while(Q--)
{
scanf("%d%d", &x, &y);
//read(x); read(y);
if(y == M) printf("%lld\n", del_M_las(x, ));
else printf("%lld\n", del_N(x, y));
}
return ;
}

【NOIP2017】列队【可持久化线段树】的更多相关文章

  1. Luogu3960 NOIP2017列队(splay/线段树)

    令splay中的一个点表示一段区间,需要使用其中某个点时将区间分裂即可,剩下的都是splay的基本操作了.写的非常丑陋,注意细节.感觉考场上肯定只能靠部分分苟活了.想起来去年因为各种莫名其妙的原因50 ...

  2. 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)

    有点类似NOI2014购票 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ 这个显然是可以斜率优化的... $\frac {f(j)-f(k)}{dep_j ...

  3. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  4. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  5. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  6. HDU 4866 Shooting(持久化线段树)

    view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...

  7. 【BZOJ-3653】谈笑风生 DFS序 + 可持久化线段树

    3653: 谈笑风生 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 628  Solved: 245[Submit][Status][Discuss] ...

  8. 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树

    没什么好说的. 可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲. Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的.. #include<bits/stdc ...

  9. 【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队

    看到题目就可以想到hash 然后很自然的联想到可持久化权值线段树 WA:base取了偶数 这道题还可以用莫队做,比线段树快一些 可持久化线段树: #include<bits/stdc++.h&g ...

随机推荐

  1. [2019杭电多校第二场][hdu6599]I Love Palindrome String(回文自动机&&hash)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599 题目大意为求字符串S有多少个子串S[l,r]满足回文串的定义,并且S[l,(l+r)/2]也满足 ...

  2. [WPF自定义控件库] 关于ScrollViewer和滚动轮劫持(scroll-wheel-hijack)

    原文:[WPF自定义控件库] 关于ScrollViewer和滚动轮劫持(scroll-wheel-hijack) 1. 什么是滚动轮劫持# 这篇文章介绍一个很简单的继承自ScrollViewer的控件 ...

  3. C# xml格式字符串,插入到数据库出现非法字符

    在debug模式下快速监视看到的数据是完全正常的,即取到的是<xml>,但是把该字符串拷贝到UltraEdit中,取到的第一个字符是问号.使用正则表达式^[^<]进行替换,意思是把开 ...

  4. C#取模的理解:为什么当a<b,a%b=a?

    一,取模a%b 1,如果a>b,例如10%7=3,这是什么原因呢?可以根据下面的理解 10 =7*1+3,则模就是3 2,如果a<b,例如7%10 = 7,这时怎么得到的呢?根据下面来理解 ...

  5. maven 打包Scala代码到jar包

    idea的pom.xml文件配置 <dependencies> <dependency> <groupId>org.scala-lang</groupId&g ...

  6. java SSM框架 代码生成器 快速开发平台 websocket即时通讯 shiro redis

    A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 , ...

  7. Python中queue消息队列模块

    from queue import Queue from queue import PriorityQueue print("Queue类实现了一个基本的先进先出(FIFO)容器,使用put ...

  8. 记录cobbler报错

    出现下面这个错误解决方法 httpd does not appear to be running and proxying cobbler, or SELinux is in the way. Ori ...

  9. vue+java后台通信报403,cors解决跨域问题(该贴说的不是很清楚,不过大概如此,可再去网上查相关内容)

    前端是vue2.0,网络请求用的是axios,后端是springboot2.0 用axios向后端发送post请求,结果得到一个403无权限的错误,莫名其妙啊,我明明发送的是post请,但在chrom ...

  10. Linux学习-MySQL的主从复制高可用性解决方案MHA

    一.MHA简介 1.MHA Master High Availability,对主节点进行监控,可实现自动故障转移至其它从节点:通过提升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现, ...