题目描述

给出一个 $n\times m$ 的矩阵,第 $i$ 行第 $j$ 列的数为 $(i-1)\times m+j$ 。

现在有 $q$ 次操作,每次操作给出位置 $(x,y)$ ,取出 $(x,y)$ 位置的数,然后令 $(x,y+1)\sim (x,m)$ 的所有数向左(列减小)平移一格,再令 $(x+1,m)\sim (n,m)$ 的所有数向上(行减小)平移一格,最后将取出的数放到位置 $(n,m)$ 。

求每次取出的数是多少。


题解

Splay

考场上觉得正解一定不是Splay(以为带log的数据结构都不考),就只写了80分暴力。

事实上正解还真是数据结构 = =

本题使用Splay来做就变成了真真正正的模拟题。

我们对 每行除最后一列以外的部分 和 最后一列 建Splay,那么就只需要实现:取出区间中第 $k$ 个数、将一个数插入到序列最后一个数的后面。直接使用Splay模拟即可。

然而初始的数有 $n\times m$ 个,不能直接加入到Splay中。注意到原来的数都是等差数列,因此可以参考 bzoj3678 的方法,打上等差数列标记即可。

时间复杂度 $O(n\log n)$ ,常数较大,在loj上可过,在luogu上需要开O2才能过。

#include <cstdio>
#include <cctype>
#include <algorithm>
#define N 10000010
using namespace std;
typedef long long ll;
int fa[N] , c[2][N] , s[N] , si[N] , root[300010] , tot;
ll w[N] , d[N];
inline char nc()
{
static char buf[100000] , *p1 , *p2;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
inline int read()
{
int ret = 0; char ch = nc();
while(!isdigit(ch)) ch = nc();
while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc();
return ret;
}
inline void pushup(int x)
{
si[x] = si[c[0][x]] + si[c[1][x]] + s[x];
}
inline void rotate(int &k , int x)
{
int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
if(y == k) k = x;
else c[c[1][z] == y][z] = x;
fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
pushup(y) , pushup(x);
}
inline void splay(int &k , int x)
{
int y , z;
while(x != k)
{
y = fa[x] , z = fa[y];
if(y != k)
{
if((c[0][y] == x) ^ (c[0][z] == y)) rotate(k , x);
else rotate(k , y);
}
rotate(k , x);
}
}
int find(int k , int x)
{
if(x <= si[c[0][k]]) return find(c[0][k] , x);
if(x > si[c[0][k]] + s[k]) return find(c[1][k] , x - si[c[0][k]] - s[k]);
x -= si[c[0][k]];
if(x > 1) fa[++tot] = k , w[tot] = w[k] , d[tot] = d[k] , s[tot] = x - 1 , c[0][tot] = c[0][k] , pushup(tot) , fa[c[0][tot]] = c[0][k] = tot;
if(x < s[k]) fa[++tot] = k , w[tot] = w[k] + d[k] * x , d[tot] = d[k] , s[tot] = s[k] - x , c[1][tot] = c[1][k] , pushup(tot) , fa[c[1][tot]] = c[1][k] = tot;
w[k] += d[k] * (x - 1) , s[k] = 1;
return k;
}
inline int split(int &rt , int l , int r)
{
int a = find(rt , l) , b = find(rt , r + 2);
splay(rt , a) , splay(c[1][rt] , b);
return c[0][c[1][rt]];
}
int main()
{
int n = read() , m = read() , i , q = read() , x , y , u , v;
for(i = 1 ; i <= n ; i ++ )
{
root[i] = ++tot , w[tot] = 1ll * (i - 1) * m + 1 , d[tot] = 1 , s[tot] = m - 1 , si[tot] = m + 1;
c[0][root[i]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[i];
c[1][root[i]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[i];
}
root[n + 1] = ++tot , w[tot] = m , d[tot] = m , s[tot] = n , si[tot] = n + 2;
c[0][root[n + 1]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[n + 1];
c[1][root[n + 1]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[n + 1];
while(q -- )
{
x = read() , y = read();
if(y == m)
{
printf("%lld\n" , w[u = split(root[n + 1] , x , x)]);
c[0][fa[u]] = 0 , pushup(fa[u]) , pushup(fa[fa[u]]) , fa[u] = 0;
split(root[n + 1] , n , n - 1);
fa[u] = c[1][root[n + 1]] , c[0][fa[u]] = u , pushup(fa[u]) , pushup(fa[fa[u]]);
}
else
{
printf("%lld\n" , w[u = split(root[x] , y , y)]);
c[0][fa[u]] = 0 , pushup(fa[u]) , pushup(fa[fa[u]]) , fa[u] = 0;
v = split(root[n + 1] , x , x);
c[0][fa[v]] = 0 , pushup(fa[v]) , pushup(fa[fa[v]]) , fa[v] = 0;
split(root[x] , m - 1 , m - 2);
fa[v] = c[1][root[x]] , c[0][fa[v]] = v , pushup(fa[v]) , pushup(fa[fa[v]]);
split(root[n + 1] , n , n - 1);
fa[u] = c[1][root[n + 1]] , c[0][fa[u]] = u , pushup(fa[u]) , pushup(fa[fa[u]]);
}
}
return 0;
}

【loj2319】[NOIP2017]列队 Splay(卡过)的更多相关文章

  1. Luogu 3960 [NOIP2017] 列队 - splay|线段树

    题解 是我从来没有做过的裂点splay... 看的时候还是很懵逼的QAQ. 把最后一列的$n$个数放在一个平衡树中, 有 $n$ 个点 剩下的$n$行数, 每行都开一个平衡树,开始时每棵树中仅有$1$ ...

  2. [NOIP2017]列队 离线+SBT

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

  3. 题解[NOIP2017] 列队

    题解[NOIP2017] 列队 题面 解析 看到这题时感觉这个编号很难维护啊? 后来看了lzf大佬的题解才会.. 首先,考虑一个稍微暴力的做法, 维护每一行的前\(m-1\)个人和最后一列的\(n\) ...

  4. [NOIP2017]列队 (Splay)

    题目链接 NOIP2017真的是不按常理出牌: 1.数学题不在Day2T1 2.一道水题一道细节极多的模拟题一道不知道怎么形容的题(小凯的疑惑)(因为我太菜了) 3.3道大火题 当时看到列队这题是毫无 ...

  5. 【NOIP2017】列队 splay

    当年太菜了啊,连$60$分的暴力都没拿满,只打了一个$30$分的. 考虑到这题最多只会询问到$30W$个点,且整个矩阵会去到$30W\times 30W$,显然不能将所有的点存下来. 对于每一行(除最 ...

  6. [NOIP2017]列队(线段树/裂点splay)

    考虑n=1的做法,就是支持: 1.在线删一个数 2.在结尾加一个数 3.查询序列的第y个数 用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可. 对于 ...

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

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

  8. NOIP2017列队(phalanx)解题报告

    列队作为NOIP2017最后一道题,其实并不难,只是相对于其它题目,有点小小的工业 首先,这道题我用splay维护的,如果你不会splay,又想学一下splay,可以来这里学一学,接下来步入正题 首先 ...

  9. NOIP2017 列队 题解报告【56行线段树】

    题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...

随机推荐

  1. Ubuntu + apache + Mysql +php

    发生了乱码问题: 打开apache配置文件: sudo gedit /etc/apache2/apache2.conf,在最后面加上:AddDefaultCharset UTF-8,如果还乱码,再将U ...

  2. [arc068E]Snuke Line-[树状数组]

    Description 传送门 Solution 假如想直接YY对于每一个d会有多少种商品满足条件,em反正我搞不定. 然后大佬的题解告诉我说:搞不定?那就不搞它啊,反过来不就得了? 好吧.我们来考虑 ...

  3. 优步UBER司机全国各地奖励政策汇总 (4月18日-4月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. 初始CSS模板

    /*开始 初始CSS模板 开始*/ body, div, address, blockquote, iframe, ul, ol, dl, dt, dd, li, dl, h1, h2, h3, h4 ...

  5. QQ在线交谈一句代码搞定

    现在有很多网页都有QQ在线咨询,还有什么QQ客服什么的,看着很高大上的一个功能,其实要实现很简单,只需要一句代码就搞定. 还是按以前的套路,先看效果图,再晒源代码 点击图标 再点击 就可以聊天了 再来 ...

  6. Vue学习计划基础笔记(四) - 事件处理

    事件处理 目标: 熟练掌握事件监听的方式,熟悉事件处理方式以及各类事件修饰符 理解在html中监听事件的意义 监听事件(v-on) 类似普通的on,例如v-on:click或@click就相当于普通的 ...

  7. RHCE6.0上午的考试一键完成

    #!/sbin/bash # #initial envirment #variable define IPADDR=192.168.0.12 NETMASK=255.255.255.0 HOSTNAM ...

  8. Literature Books

    Lean In (Sheryl Sandberg) Option B (Sheryl Sandberg) Ready Player One

  9. How to pass an Amazon account review

    Have you ever sold products on Amazon? How about sold so much within the first week that amazon deci ...

  10. ExpressJS基础概念及简单Server架设

    NodeJS Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.js 的包 ...