题目描述

给出一个 $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才能过。

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <algorithm>
  4. #define N 10000010
  5. using namespace std;
  6. typedef long long ll;
  7. int fa[N] , c[2][N] , s[N] , si[N] , root[300010] , tot;
  8. ll w[N] , d[N];
  9. inline char nc()
  10. {
  11. static char buf[100000] , *p1 , *p2;
  12. return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ;
  13. }
  14. inline int read()
  15. {
  16. int ret = 0; char ch = nc();
  17. while(!isdigit(ch)) ch = nc();
  18. while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc();
  19. return ret;
  20. }
  21. inline void pushup(int x)
  22. {
  23. si[x] = si[c[0][x]] + si[c[1][x]] + s[x];
  24. }
  25. inline void rotate(int &k , int x)
  26. {
  27. int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
  28. if(y == k) k = x;
  29. else c[c[1][z] == y][z] = x;
  30. fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
  31. pushup(y) , pushup(x);
  32. }
  33. inline void splay(int &k , int x)
  34. {
  35. int y , z;
  36. while(x != k)
  37. {
  38. y = fa[x] , z = fa[y];
  39. if(y != k)
  40. {
  41. if((c[0][y] == x) ^ (c[0][z] == y)) rotate(k , x);
  42. else rotate(k , y);
  43. }
  44. rotate(k , x);
  45. }
  46. }
  47. int find(int k , int x)
  48. {
  49. if(x <= si[c[0][k]]) return find(c[0][k] , x);
  50. if(x > si[c[0][k]] + s[k]) return find(c[1][k] , x - si[c[0][k]] - s[k]);
  51. x -= si[c[0][k]];
  52. 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;
  53. 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;
  54. w[k] += d[k] * (x - 1) , s[k] = 1;
  55. return k;
  56. }
  57. inline int split(int &rt , int l , int r)
  58. {
  59. int a = find(rt , l) , b = find(rt , r + 2);
  60. splay(rt , a) , splay(c[1][rt] , b);
  61. return c[0][c[1][rt]];
  62. }
  63. int main()
  64. {
  65. int n = read() , m = read() , i , q = read() , x , y , u , v;
  66. for(i = 1 ; i <= n ; i ++ )
  67. {
  68. root[i] = ++tot , w[tot] = 1ll * (i - 1) * m + 1 , d[tot] = 1 , s[tot] = m - 1 , si[tot] = m + 1;
  69. c[0][root[i]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[i];
  70. c[1][root[i]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[i];
  71. }
  72. root[n + 1] = ++tot , w[tot] = m , d[tot] = m , s[tot] = n , si[tot] = n + 2;
  73. c[0][root[n + 1]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[n + 1];
  74. c[1][root[n + 1]] = ++tot , s[tot] = 1 , si[tot] = 1 , fa[tot] = root[n + 1];
  75. while(q -- )
  76. {
  77. x = read() , y = read();
  78. if(y == m)
  79. {
  80. printf("%lld\n" , w[u = split(root[n + 1] , x , x)]);
  81. c[0][fa[u]] = 0 , pushup(fa[u]) , pushup(fa[fa[u]]) , fa[u] = 0;
  82. split(root[n + 1] , n , n - 1);
  83. fa[u] = c[1][root[n + 1]] , c[0][fa[u]] = u , pushup(fa[u]) , pushup(fa[fa[u]]);
  84. }
  85. else
  86. {
  87. printf("%lld\n" , w[u = split(root[x] , y , y)]);
  88. c[0][fa[u]] = 0 , pushup(fa[u]) , pushup(fa[fa[u]]) , fa[u] = 0;
  89. v = split(root[n + 1] , x , x);
  90. c[0][fa[v]] = 0 , pushup(fa[v]) , pushup(fa[fa[v]]) , fa[v] = 0;
  91. split(root[x] , m - 1 , m - 2);
  92. fa[v] = c[1][root[x]] , c[0][fa[v]] = v , pushup(fa[v]) , pushup(fa[fa[v]]);
  93. split(root[n + 1] , n , n - 1);
  94. fa[u] = c[1][root[n + 1]] , c[0][fa[u]] = u , pushup(fa[u]) , pushup(fa[fa[u]]);
  95. }
  96. }
  97. return 0;
  98. }

【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. day 3 私有属性,私有方法,__del__

    1.隐藏对象的属性 如果有一个对象,当需要对其进行修改属性时,有2种方法 对象名.属性名 = 数据 ---->直接修改 对象名.方法名() ---->间接修改 1)版本1:直接修改 对象的 ...

  2. day 11 名片管理系统

    1 思路 #名片1 名片2 {"name":"alex","age":18,"QQ":12123} {"nam ...

  3. WordPress用户导入Drupal7并登录

    用户导入比较简单.使用Feeds模块中的Feeds Import工具就行. 不过有个不好地方的,导入前密码是明文,导入后该模块会自动转换为Drupal加密后的密码. 这需要导入后原wp的用户也能登录d ...

  4. 【MYSQL经验】MYSQL经验总结

    1.决定是否添加一个新的所以并部署它需要考虑很多因素

  5. SQL基本的45题

    -- 查询Student表中的所有记录的Sname.Ssex和Class列.SELECT Sname,Ssex,Class from student -- 查询教师所有的单位即不重复的Depart列. ...

  6. 微信小程序模板消息群发解决思路

    基于微信的通知渠道,微信为开发者提供了可以高效触达用户的模板消息能力,以便实现服务的闭环并提供更佳的体验.(微信6.5.2及以上版本支持模板功能.低于该版本将无法收到模板消息.) 模板推送位置:服务通 ...

  7. TensorFlow深度学习实战---循环神经网络

    循环神经网络(recurrent neural network,RNN)-------------------------重要结构(长短时记忆网络( long short-term memory,LS ...

  8. JMeter测试WebSocket的经验总结

    最近有一个微信聊天系统的项目需要性能测试,既然是测试微信聊天,肯定绕不开websocket接口的测试,首选工具是Jmeter,网上能搜到现成的方法,但是网上提供的jar包往往不是最新的,既然是用最新版 ...

  9. 【坚持】Selenium+Python学习之从读懂代码开始 DAY1

    学习Selenium+Python已经好几个月了,但越学发现不懂的东西越多. 感觉最大的问题还是在于基础不扎实,决定从头开始,每天坚持读代码,写代码. 相信量变一定能到质变!!! 2018/05/09 ...

  10. Zabbix远程执行命令

    原文发表于cu:2016-06-14 Zabbix触发器(trigger)达到阀值后会有动作(action)执行:发送告警信息或执行远程命令. 本文主要配置验证zabbix执行远程命令. 一.环境 S ...