第一种用线段树,用两颗数维护区间最大值和区间的最小值,然后更新的时候如果我目前区间内的最大值比我得到的v小,那么我就把这个区间修改成v,如果我的最小值比v大,那么v就是没有用的,直接跳过,然后这样每次更新[l, r]内的最大最小值,查询的时候返回每个位置的最大值,就可以求出答案

线段树:

  1. #include<map>
  2. #include<set>
  3. #include<ctime>
  4. #include<cmath>
  5. #include<stack>
  6. #include<queue>
  7. #include<string>
  8. #include<vector>
  9. #include<cstdio>
  10. #include<cstdlib>
  11. #include<cstring>
  12. #include<iostream>
  13. #include<algorithm>
  14. #define lowbit(x) (x & (-x))
  15.  
  16. typedef unsigned long long int ull;
  17. typedef long long int ll;
  18. typedef unsigned int ui;
  19. const double pi = 4.0*atan(1.0);
  20. const int inf = 0x3f3f3f3f;
  21. const int maxn = 1e5;
  22. const int maxm = 2e5+;
  23. const int mod = <<;
  24. const double eps = 1e-;
  25. using namespace std;
  26.  
  27. int n, m;
  28. int T, tol;
  29. ui X, Y, Z;
  30. int mx[maxn << ];
  31. int mn[maxn << ];
  32. int lazy[maxn << ];
  33.  
  34. ui RNG61() {
  35. X = X ^ (X<<);
  36. X = X ^ (X>>);
  37. X = X ^ (X<<);
  38. X = X ^ (X>>);
  39. ll W = X ^ (Y ^ Z);
  40. X = Y;
  41. Y = Z;
  42. Z = W;
  43. return Z;
  44. }
  45.  
  46. void init() {
  47. memset(mx, , sizeof mx);
  48. memset(mn, , sizeof mn);
  49. memset(lazy, , sizeof lazy);
  50. }
  51.  
  52. void pushup(int root) {
  53. mx[root] = max(mx[root << ], mx[root << | ]);
  54. mn[root] = min(mn[root << ], mn[root << | ]);
  55. }
  56.  
  57. void pushdown(int root) {
  58. if(lazy[root]) {
  59. mx[root << ] = mx[root << | ] = lazy[root];
  60. mn[root << ] = mn[root << | ] = lazy[root];
  61. lazy[root << ] = lazy[root << | ] = lazy[root];
  62. lazy[root] = ;
  63. }
  64. }
  65.  
  66. void update(int left, int right, int prel, int prer, int val, int root) {
  67. if(prel <= left && right <= prer) {
  68. if(mx[root] < val) {
  69. mx[root] = mn[root] = val;
  70. lazy[root] = val;
  71. return ;
  72. }
  73. if(mn[root] > val) return ;
  74. }
  75. if(mn[root] > val) return ;
  76. pushdown(root);
  77. int mid = (left + right) >> ;
  78. if(prel <= mid) update(left, mid, prel, prer, val, root << );
  79. if(prer > mid) update(mid+, right, prel, prer, val, root << | );
  80. pushup(root);
  81. }
  82.  
  83. int query(int left, int right, int pos, int root) {
  84. if(left == right) {
  85. return mx[root];
  86. }
  87. pushdown(root);
  88. int mid = (left + right) >> ;
  89. if(pos <= mid) return query(left, mid, pos, root << );
  90. else return query(mid+, right, pos, root << | );
  91. }
  92.  
  93. int main() {
  94. scanf("%d", &T);
  95. while(T--) {
  96. scanf("%d%d%d%d%d", &n, &m, &X, &Y, &Z);
  97. init();
  98. for(int i=; i<=m; i++) {
  99. ui f1 = RNG61();
  100. ui f2 = RNG61();
  101. ui f3 = RNG61();
  102. int l = min(f1%n+, f2%n+);
  103. int r = max(f1%n+, f2%n+);
  104. int v = f3 % mod;
  105. update(, n, l, r, v, );
  106. }
  107. ll ans = ;
  108. for(int i=; i<=n; i++) {
  109. ans ^= (1ll * i * query(, n, i, ));
  110. }
  111. printf("%I64d\n", ans);
  112. }
  113. return ;
  114. }

原本的RMQ是得到每个位置的点值,然后一步一步更新成区间的最值,用

st[i][j] = max(st[i][j-1],st[i+(1<<(j-1))][j-1])

然后这里是先得到区间最值,然后往回更新到每个位置的点的最值,所以就是两个

st[i][j-1] = max(st[i][j-1], st[i][j])

st[i+(1<<(j-1))][j-1] = max(st[i+(1<<(j-1))][j-1], st[i][j])

倒着更新

然后题目里面数据很大,所以同样的log(r-l+1)/log(2.0)可能计算很多遍,可以把log(i)/log(2.0)打表出来,可以快一半的时间

ST表:

  1. #include<map>
  2. #include<set>
  3. #include<ctime>
  4. #include<cmath>
  5. #include<stack>
  6. #include<queue>
  7. #include<string>
  8. #include<vector>
  9. #include<cstdio>
  10. #include<cstdlib>
  11. #include<cstring>
  12. #include<iostream>
  13. #include<algorithm>
  14. #define lowbit(x) (x & (-x))
  15.  
  16. typedef unsigned long long int ull;
  17. typedef long long int ll;
  18. typedef unsigned int ui;
  19. const double pi = 4.0*atan(1.0);
  20. const int inf = 0x3f3f3f3f;
  21. const int maxn = 1e5;
  22. const int maxm = 2e5+;
  23. const int mod = <<;
  24. const double eps = 1e-;
  25. using namespace std;
  26.  
  27. int n, m;
  28. int T, tol;
  29. ui X, Y, Z;
  30.  
  31. int st[maxm][];
  32. int lg[maxn];
  33.  
  34. ui RNG61() {
  35. X = X ^ (X<<);
  36. X = X ^ (X>>);
  37. X = X ^ (X<<);
  38. X = X ^ (X>>);
  39. ll W = X ^ (Y ^ Z);
  40. X = Y;
  41. Y = Z;
  42. Z = W;
  43. return Z;
  44. }
  45.  
  46. void init() {
  47. memset(st, , sizeof st);
  48. }
  49.  
  50. void handle() {
  51. lg[] = -;
  52. for(int i=; i<maxn; i++) lg[i] = log(i) / log(2.0);
  53. }
  54.  
  55. int main() {
  56. handle();
  57. scanf("%d", &T);
  58. while(T--) {
  59. scanf("%d%d%d%d%d", &n, &m, &X, &Y, &Z);
  60. init();
  61. for(int i=; i<=m; i++) {
  62. ui f1 = RNG61();
  63. ui f2 = RNG61();
  64. ui f3 = RNG61();
  65. int l = min(f1%n+, f2%n+);
  66. int r = max(f1%n+, f2%n+);
  67. int v = f3 % mod;
  68. int k = lg[r-l+];
  69. st[l][k] = max(st[l][k], v);
  70. st[r-(<<k)+][k] = max(st[r-(<<k)+][k], v);
  71. }
  72. int len = log(n) / log(2.0);
  73. for(int j=len; j>=; j--) {
  74. for(int i=; i<=n; i++) {
  75. st[i][j-] = max(st[i][j-], st[i][j]);
  76. st[i+(<<(j-))][j-] = max(st[i+(<<(j-))][j-], st[i][j]);
  77. }
  78. }
  79. ll ans = ;
  80. for(int i=; i<=n; i++) ans = ans ^ (1ll * i * st[i][]);
  81. printf("%I64d\n", ans);
  82. }
  83. return ;
  84. }

Glad You Came hdu-6356(ST表 || 线段树)的更多相关文章

  1. 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径

    51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...

  2. 51nod 1593 公园晨跑 | ST表(线段树?)思维题

    51nod 1593 公园晨跑 有一只猴子,他生活在一个环形的公园里.有n棵树围绕着公园.第i棵树和第i+1棵树之间的距离是 di ,而第n棵树和第一棵树之间的距离是 dn .第i棵树的高度是 hi ...

  3. Codeforces 487B Strip (ST表+线段树维护DP 或 单调队列优化DP)

    题目链接 Strip 题意   把一个数列分成连续的$k$段,要求满足每一段内的元素最大值和最小值的差值不超过$s$, 同时每一段内的元素个数要大于等于$l$, 求$k$的最小值. 考虑$DP$ 设$ ...

  4. bzoj 1699: [Usaco2007 Jan]Balanced Lineup排队【st表||线段树】

    要求区间取min和max,可以用st表或线段树维护 st表 #include<iostream> #include<cstdio> using namespace std; c ...

  5. (DP ST表 线段树)51NOD 1174 区间中最大的数

    给出一个有N个数的序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,最大的数是多少.   例如: 1 7 6 3 1.i = 1, j = 3,对应的数为7 6 3,最大的数为7. ...

  6. [luoguP1816] 忠诚(st表 || 线段树)

    传送门 其实我就是想练练 st表 本以为学了线段树可以省点事不学 st表 了 但是后缀数组中用 st表 貌似很方便 所以还是学了吧,反正也不难 ——代码 #include <cstdio> ...

  7. RMQ--树状数组,ST表,线段树

    RMQ Range Minimum/Maximum Query 区间最值问题 树状数组 https://www.cnblogs.com/xenny/p/9739600.html lowbit(x) x ...

  8. st表、树状数组与线段树 笔记与思路整理

    已更新(2/3):st表.树状数组 st表.树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题. 一.ST表(Sparse ...

  9. Hdu5737-Differencia(有序表线段树)

    题意很直观,我就不说了. 解析:这是我以前没有接触过的线段树类型,有序表线段树,每个节点申请了两段空间,主要是为了保存左边儿子会有多少比v小的,右边儿子会有多少比v小 的,所以在建树过程中要归并排序. ...

随机推荐

  1. [转][mysql]创建函数失败(1418错误)mysql双主模式导致的问题

    https://blog.csdn.net/qq523786283/article/details/75102170

  2. Python&R&量化 金融之路

    [ 分类 ]- 金融之路 - 闲云孤鹤(人生在世五十年,大千世界一瞬间,浮生若梦,仿佛间,幻境一场,生者无常,终须尽.) - CSDN博客 https://blog.csdn.net/robertso ...

  3. vue传参二

    <template> <ul> <li v-for="(value,key,index) in list" :key="index" ...

  4. SQLServer2016 之后增加了索引列数的限制 从 16个列 增加到了 32个列

    创建带有包含列的索引 https://docs.microsoft.com/zh-cn/sql/relational-databases/indexes/create-indexes-with-inc ...

  5. opencv自带fast_math.hpp

    cvRound cvFloor cvCeil cvIsNaN cvIsInf

  6. Day 6-1计算机网络基础&TCP/IP

    按照功能不同,人们将互联网协议分为osi七层或tcp/ip五层或tcp/ip四层(我们只需要掌握tcp/ip五层协议即可) 每层运行常见物理设备: TCP/IP协议: Transmission Con ...

  7. Sublime Text3 配置 NodeJs 开发环境

    题外话:使用visual studio开发NodeJs也是很方便,只需要安装插件即可. 本着对Sublime Text3的喜爱,尤其是最近更新后,界面和功能上感觉更nice了,那就配置一发环境吧! ( ...

  8. 转《service worker在移动端H5项目的应用》

    1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将 Web App ...

  9. Golang的md5 hash计算

    Golang计算md5值的方法都是接收byte型slice([]byte).而且使用习惯上也觉得略奇怪. 看了好几个例子才看懂. 感觉Golang标准库在设计这些模块的时候,都会考虑使用带New关键字 ...

  10. kubernetes资源类别介绍

    类别 名称 资源对象 Pod.ReplicaSet.ReplicationController.Deployment.StatefulSet.DaemonSet.Job.CronJob.Horizon ...