题意简述

有一个n × m 的矩阵,第i行第j列元素编号为(i - 1)× m +j

每次将一个数取出,其他元素依次向左,向上填补空缺,最后将取出的数放入矩阵最后一格

求每次取出数的编号

题解思路

由于最后一列较为特殊,只有当取出的数位于最后一列,向上填补空缺时才有影响,所有特殊考虑

对于每一行的(m - 1)个元素 和 最后一列元素都维护一个splay

进行删除第k个元素 和 在末尾插入元素 两个操作

代码

#include <cstdio>
#include <cassert>
using namespace std;
typedef long long ll;
struct Node
{
ll l, r;
Node *c[2];
int s;
Node() {l = r = 0; s = 0; c[0] = c[1] = 0; }
Node(ll x) {l = r = x; s = 1; c[0] = c[1] = 0; }
Node(ll l, ll r) {this -> l = l; this -> r = r; s = r - l + 1; c[0] = c[1] = 0; }
int get(bool b){return c[b] ? c[b] -> s : 0; }
void upt(){s = get(0) + get(1) + (r - l + 1); }
int cmp(int x){return (x > get(0) && x <= get(0) + r - l + 1) ? -1 : x > get(0); }
}*r[300010];
int n, m, q, x, y;
void rtt(Node* &o, bool b)
{
Node* t = o -> c[b ^ 1];
o -> c[b ^ 1] = t -> c[b];
t -> c[b] = o;
o -> upt();
t -> upt();
o = t;
}
void splay(Node* &o, int k)
{
if (!o) return;
int d1 = o -> cmp(k);
if (d1 == -1) return;
int xx = k - d1 * (o -> s - o -> get(1));
int d2 = o -> c[d1] -> cmp(xx);
if (d2 == -1) rtt(o, d1 ^ 1);
else
{
splay(o -> c[d1] -> c[d2], xx - d2 * (o -> c[d1] -> s - o -> c[d1] -> get(1)));
if (d1 == d2) rtt(o, d2 ^ 1);
else rtt(o -> c[d1], d2 ^ 1);
rtt(o, d1 ^ 1);
}
}
void ins(Node* &o, Node* x)
{
if (!o) {o = x; return; }
splay(o, o -> s);
o -> c[1] = x;
o -> upt();
}
Node* del(Node* &o, int k)
{
splay(o, k);
if (o -> l == o -> r)
{
Node* t = o;
if (!o -> c[0]) o = o -> c[1];
else
{
splay(o -> c[0], o -> get(0));
o -> c[0] -> c[1] = o -> c[1];
o = o -> c[0];
o -> upt();
}
t -> s = 1;
t -> c[0] = t -> c[1] = 0;
return t;
}
ll xxx = o -> l + k - o -> get(0) - 1;
Node* x = new Node(o -> l, xxx - 1);
o -> l = xxx + 1;
x -> c[0] = o -> c[0];
o -> c[0] = x;
x -> upt();
o -> upt();
return new Node(xxx);
}
int main()
{
scanf("%d%d%d", &n, &m, &q);
for (register int i = 1; i <= n; ++i)
{
r[i] = new Node((ll)(i - 1) * m + 1, (ll)i * m - 1);
ins(r[0], new Node((ll)i * m));
}
for (register int i = 1; i <= q; ++i)
{
scanf("%d%d", &x, &y);
Node* idx;
if (y == m)
{
printf("%lld\n", (idx = del(r[0], x)) -> l);
ins(r[0], idx);
}
else
{
ins(r[x], del(r[0], x));
printf("%lld\n", (idx = del(r[x], y)) -> l);
ins(r[0], idx);
}
}
}

洛谷 P1960 列队的更多相关文章

  1. 洛谷P3960 列队(NOIP2017)(Splay)

    洛谷题目传送门 最弱的Splay...... 暴力模拟30分(NOIP2017实际得分,因为那时连Splay都不会)...... 发现只是一个点从序列里搬到了另一个位置,其它点的相对位置都没变,可以想 ...

  2. 洛谷 P3960 列队 解题报告

    P3960 列队 题目描述 \(Sylvia\)是一个热爱学习的女♂孩子. 前段时间,\(Sylvia\)参加了学校的军训.众所周知,军训的时候需要站方阵. \(Sylvia\)所在的方阵中有\(n ...

  3. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

  4. 洛谷P3960 列队(动态开节点线段树)

    题意 题目链接 Sol 看不懂splay..,看不懂树状数组... 只会暴力动态开节点线段树 观察之后不难发现,我们对于行和列需要支持的操作都是相同的:找到第\(k\)大的元素并删除,在末尾插入一个元 ...

  5. 洛谷P3960 列队(Splay)

    传送门 感觉自己好久不打数据结构已经完全不会了orz…… 据说正解树状数组?然而并不会 首先考虑一下每一次操作,就是把一个人从这一行中取出并放到行的最后,再从最后一列取出放到列的最后 那么这两种操作其 ...

  6. 洛谷 P3960 列队【线段树】

    用动态开点线段树分别维护每一行和最后一列,线段树的作用是记录被选的点的个数以及查询第k个没被选的点,每次修改,从行里标记被选的点,从最后一列标记向左看齐之后少的点,然后用vector维护行列的新增点 ...

  7. 洛谷 P3960 列队

    https://www.luogu.org/problemnew/show/P3960 常数超大的treap #pragma GCC optimize("Ofast") #incl ...

  8. 洛谷P3960 列队 Splay

    其实思路并不算太难,就是代码量相对较大. 我们将一次离队转换为一次删除和两次加入,这样就可以保证空间是动态分配的,最大也不会暴空间. 说实话写之前感觉会很恶心,但是代码量就还好吧,有些细节需要特殊注意 ...

  9. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

随机推荐

  1. springboot不同环境打包

    1. 场景描述 springboot+maven打包,项目中经常用到不同的环境下打包不同的配置文件,比如连接的数据库.配置文件.日志文件级别等都不一样. 2. 解决方案 在pom.xml文件中定义 2 ...

  2. MYSQL语句强化练习

    之前发现自己写sql不怎么得心应手,总是百度零零散散的学习一下,所以在空闲的时候自己就专门找一下mysql的强化题敲一下练习一下,简要记录一下,sql写着写着就会越来越熟练,总之要自己加油! 表结构 ...

  3. 学习4:总结# 1.列表 # 2.元祖 # 3.range

    列表 -- list 有序,可变的,索引, 作用:存储数据的,支持很多种数据类型 定义方式: lst = [1,"alex","黑哥"] 增: append 追 ...

  4. [原创]实现MongoDB数据库审计SQL语句的脚本

    功能:实现具体显示mongodb数据库表操作语句的状态和情况,使用awk和shell实现抓取和分析处理.脚本内容如下: #!/bin/bash if [ $# == 0 ];then echo &qu ...

  5. UVA297 四分树 Quadtrees 题解

    题目链接: https://www.luogu.org/problemnew/show/UVA297 附几道推荐题目(先完成再食用此题效果更佳) https://www.luogu.org/probl ...

  6. RabbitMQ 从入门到精通(二)

    目录 1. 消息如何保障百分之百的投递成功? 1.1 方案一:消息落库,对消息状态进行打标 1.2 方案二:消息的延迟投递,做二次确认,回调检查 2. 幂等性 2.1 幂等性是什么? 2.2 消息端幂 ...

  7. Netty编码流程及WriteAndFlush()的实现

    编码器的执行时机 首先, 我们想通过服务端,往客户端发送数据, 通常我们会调用ctx.writeAndFlush(数据)的方式, 入参位置的数据可能是基本数据类型,也可能对象 其次,编码器同样属于ha ...

  8. 用tcp协议实现一个并发的socketserver 进行密文登录

    先在客户端进行摘要,客户端把用户名作为盐. 然后在服务端进行二次摘要,用固定的盐(不能让别人知道你的盐是什么),然后存到文件中,密文存储.或者和文件中的密文对比. 这样即使在网络上用户信息被截获,和存 ...

  9. 2019杭电多校第二场hdu6601 Keen On Everything But Triangle

    Keen On Everything But Triangle 题目传送门 解题思路 利用主席树求区间第k小,先求区间内最大的值,再求第二大,第三大--直到找到连续的三个数可以构成一个三角形.因为对于 ...

  10. antd pro中如何使用mock数据以及调用接口

    antd pro的底层基础框架使用的是dva,dva采用effect的方式来管理同步化异步 在dva中主要分为3层 services  models  components models层用于存放数据 ...