题目描述
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 列的学生离队。
在有学生离队后,队伍中出现了一个空位。为了队伍的整齐,教官会依次下达 这样的两条指令:
-
向左看齐。这时第一列保持不动,所有学生向左填补空缺。不难发现在这条 指令之后,空位在第 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 列。
输出格式:
按照事件输入的顺序,每一个事件输出一行一个整数,表示这个离队事件中离队学 生的编号。
刚拿到这道题的时候,的确是无从下手的感觉,知道有这样的一道题,【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后面去。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include