CF

题意

有一个长度为n × k (<=1E9)的数组,有区间修改和区间查询最小值的操作。

思路

由于数组过大,直接做显然不行。

有两种做法,可以用动态开点版本的线段树,或者离线搞(还没搞)(搞好了)。

注意只有1E5次操作,所以真正被更新到的区间并不多,最差单次新开2×log(1E9)。

对于新开的区间的最小值,可以这样计算,如果区间表示的值大于n,那就是原来长度为n的区间的最小值,小于n的话,在ST表中查询即可。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define pb push_back
  4. #define fi first
  5. #define se second
  6. #define debug(x) cerr<<#x << " := " << x << endl;
  7. #define bug cerr<<"-----------------------"<<endl;
  8. #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  9.  
  10. typedef long long ll;
  11. typedef long double ld;
  12. typedef pair<int, int> pii;
  13. typedef pair<ll, ll> pll;
  14.  
  15. template<class T> void _R(T &x) { cin >> x; }
  16. void _R(int &x) { scanf("%d", &x); }
  17. void _R(ll &x) { scanf("%lld", &x); }
  18. void _R(double &x) { scanf("%lf", &x); }
  19. void _R(char &x) { scanf(" %c", &x); }
  20. void _R(char *x) { scanf("%s", x); }
  21. void R() {}
  22. template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
  23.  
  24. template<typename T>
  25. inline T read(T&x){
  26. x=;int f=;char ch=getchar();
  27. while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
  28. while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
  29. return x=f?-x:x;
  30. }
  31.  
  32. const int inf = 0x3f3f3f3f;
  33.  
  34. const int mod = 1e9+;
  35.  
  36. /**********showtime************/
  37.  
  38. const int maxn = 1e5+;
  39. int b[maxn];
  40.  
  41. int st[maxn][], Log[maxn];
  42. void init_st(int n) {
  43. Log[] = -;
  44. for(int i=; i<=n; i++) {
  45. Log[i] = Log[i>>] + ;
  46. st[i][] = b[i];
  47. }
  48. for(int j=; (<<j) <= n; j++) {
  49. for(int i=; i + (<<j) - <= n; i++) {
  50. st[i][j] = min(st[i][j-], st[i+ (<<(j-))][j-]);
  51. }
  52. }
  53. }
  54. int rmq_st(int L, int R) {
  55. int k = Log[R - L + ];
  56. return min(st[L][k], st[R-(<<k)+][k]);
  57. }
  58. int n,k;
  59. int getmin(int le, int ri) {
  60. if(ri - le + >= n) return rmq_st(, n);
  61. int L = le % n; if(L == ) L = n;
  62. int R = ri % n; if(R == ) R = n;
  63. if(L <= R) return rmq_st(L, R);
  64. return min(rmq_st(L, n), rmq_st(, R));
  65. }
  66. struct Node{
  67. int le, ri;
  68. int lc,rc;
  69. int val, tag;
  70. } tree[maxn * ];
  71. int tot = ;
  72. int newNode(int le, int ri) {
  73. tot++;
  74. tree[tot].le = le;
  75. tree[tot].ri = ri;
  76. tree[tot].lc = tree[tot].rc = ;
  77. tree[tot].val = getmin(le, ri);
  78. tree[tot].tag = ;
  79. return tot;
  80. }
  81. void pushdown(int rt) {
  82. tree[tree[rt].lc].val = tree[tree[rt].lc].tag = tree[rt].tag;
  83. tree[tree[rt].rc].val = tree[tree[rt].rc].tag = tree[rt].tag;
  84. tree[rt].tag = ;
  85. }
  86. void update(int L, int R, int b, int rt) {
  87. if(L<=tree[rt].le && tree[rt].ri <= R) {
  88. tree[rt].val = tree[rt].tag = b;
  89. return;
  90. }
  91. int mid = (tree[rt].le + tree[rt].ri) >> ;
  92. if(tree[rt].lc == ) tree[rt].lc = newNode(tree[rt].le, mid);
  93. if(tree[rt].rc == ) tree[rt].rc = newNode(mid+, tree[rt].ri);
  94. if(tree[rt].tag) pushdown(rt);
  95. if(mid >= L) update(L, R, b, tree[rt].lc);
  96. if(mid < R) update(L, R, b, tree[rt].rc);
  97. tree[rt].val = min(tree[tree[rt].lc].val, tree[tree[rt].rc].val);
  98. }
  99. int query(int L, int R, int rt) {
  100. if(L <= tree[rt].le && tree[rt].ri <= R) {
  101. return tree[rt].val;
  102. }
  103.  
  104. int mid = (tree[rt].le + tree[rt].ri) >> ;
  105. if(tree[rt].lc == ) tree[rt].lc = newNode(tree[rt].le, mid);
  106. if(tree[rt].rc == ) tree[rt].rc = newNode(mid+, tree[rt].ri);
  107. if(tree[rt].tag) pushdown(rt);
  108. int res = inf;
  109. if(mid >= L) res = min(res, query(L, R, tree[rt].lc));
  110. if(mid < R) res = min(res, query(L, R, tree[rt].rc));
  111. tree[rt].val = min(tree[tree[rt].lc].val, tree[tree[rt].rc].val);
  112. return res;
  113. }
  114. int main(){
  115. scanf("%d%d", &n, &k);
  116. for(int i=; i<=n; i++) scanf("%d", &b[i]);
  117. init_st(n);
  118. int q; scanf("%d", &q);
  119. newNode(, n * k);
  120. while(q--) {
  121. int op;
  122. scanf("%d", &op);
  123. if(op == ) {
  124. int le,ri,x;
  125. scanf("%d%d%d", &le, &ri, &x);
  126. update(le, ri, x, );
  127. }
  128. else {
  129. int le, ri;
  130. scanf("%d%d", &le, &ri);
  131. printf("%d\n", query(le, ri, ));
  132. }
  133. }
  134. return ;
  135. }

离线的话,我们可以记录下所有被问到的点,然后我们可以压缩原来长度为1E9的数组:问到的点保持不变,而相邻两点之间的区间压缩成一个点,保存这段区间的最小值即可。

  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <algorithm>
  5. using namespace std;
  6. #define pb push_back
  7. #define fi first
  8. #define se second
  9. #define debug(x) cerr<<#x << " := " << x << endl;
  10. #define bug cerr<<"-----------------------"<<endl;
  11. #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  12.  
  13. typedef long long ll;
  14. typedef long double ld;
  15. typedef pair<int, int> pii;
  16. typedef pair<ll, ll> pll;
  17.  
  18. template<class T> void _R(T &x) { cin >> x; }
  19. void _R(int &x) { scanf("%d", &x); }
  20. void _R(ll &x) { scanf("%lld", &x); }
  21. void _R(double &x) { scanf("%lf", &x); }
  22. void _R(char &x) { scanf(" %c", &x); }
  23. void _R(char *x) { scanf("%s", x); }
  24. void R() {}
  25. template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
  26.  
  27. template<typename T>
  28. inline T read(T&x){
  29. x=;int f=;char ch=getchar();
  30. while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
  31. while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
  32. return x=f?-x:x;
  33. }
  34.  
  35. const int inf = 0x3f3f3f3f;
  36.  
  37. const int mod = 1e9+;
  38.  
  39. /**********showtime************/
  40.  
  41. const int maxn = 1e5+;
  42. int b[maxn];
  43. struct Query{
  44. int op;
  45. int le,ri;
  46. int x;
  47. } ask[maxn];
  48. vector<int>v, nv,node;
  49.  
  50. int n,k;
  51. int st[maxn][];
  52. int Log[maxn];
  53.  
  54. void init_st(int n){
  55. Log[] = -;
  56. for(int i = ; i<=n; i++) {
  57. st[i][] = b[i];
  58. Log[i] = Log[i>>] + ;
  59. }
  60.  
  61. for(int j=; (<<j) <= n; j++) {
  62. for(int i=; i + ( << j) - <= n; i ++) {
  63. st[i][j] = min(st[i][j-], st[i + (<<(j-)) ][j-]);
  64. }
  65. }
  66. }
  67. int get(int L, int R) {
  68. int k = Log[R - L + ];
  69. return min(st[L][k], st[R-(<<k)+][k]);
  70. }
  71. int getmin(int le, int ri) {
  72. if(ri - le + >= n)
  73. return get(, n);
  74. int l = le % n; if(!l) l = n;
  75. int r = ri % n; if(!r) r = n;
  76. if(l <= r) return get(l, r);
  77. return min(get(l, n), get(, r));
  78. }
  79.  
  80. int getid(int val) {
  81. return lower_bound(nv.begin(), nv.end(), val) - nv.begin() + ;
  82. }
  83.  
  84. int mn[maxn*],lazy[maxn * ];
  85. void build(int le, int ri, int rt) {
  86. if(le == ri) {
  87. mn[rt] = node[le-];
  88. return;
  89. }
  90. int mid = (le + ri) >> ;
  91. build(le, mid, rt<<);
  92. build(mid+, ri, rt<<|);
  93. mn[rt] = min(mn[rt<<], mn[rt<<|]);
  94. }
  95. void pushdown(int rt) {
  96. mn[rt<<] = mn[rt<<|] = lazy[rt];
  97. lazy[rt<<] = lazy[rt<<|] = lazy[rt];
  98. lazy[rt] = ;
  99. }
  100. void update(int L, int R,int x, int le, int ri, int rt) {
  101. if(le >= L && ri <= R){
  102. lazy[rt] = x;
  103. mn[rt] = x;
  104. return ;
  105. }
  106. if(lazy[rt]) pushdown(rt);
  107. int mid = (le + ri) >> ;
  108. if(mid >= L) update(L, R, x, le, mid, rt<<);
  109. if(mid < R) update(L, R, x, mid+, ri, rt<<|);
  110. mn[rt] = min(mn[rt<<], mn[rt<<|]);
  111. }
  112. int query(int L, int R,int le, int ri, int rt) {
  113. if(le >= L && ri <= R) {
  114. return mn[rt];
  115. }
  116. if(lazy[rt]) pushdown(rt);
  117. int mid = (le + ri) >> ;
  118. int res = inf;
  119. if(mid >= L) res = min(res, query(L, R, le, mid, rt<<));
  120. if(mid < R) res = min(res, query(L, R, mid+,ri, rt<<|));
  121. mn[rt] = min(mn[rt<<], mn[rt<<|]);
  122. return res;
  123. }
  124. int main(){
  125. scanf("%d%d", &n, &k);
  126. for(int i=; i<=n; i++) scanf("%d", &b[i]);
  127. init_st(n);
  128. int q; scanf("%d", &q);
  129. for(int i=; i<=q; i++){
  130. int op;
  131. scanf("%d", &op);
  132. if(op == ) {
  133. ask[i].op = op;
  134. scanf("%d%d%d", &ask[i].le, &ask[i].ri, &ask[i].x);
  135. v.pb(ask[i].le);
  136. v.pb(ask[i].ri);
  137. }
  138. else{
  139. ask[i].op = op;
  140. scanf("%d%d", &ask[i].le, &ask[i].ri);
  141. v.pb(ask[i].le);
  142. v.pb(ask[i].ri);
  143. }
  144. }
  145. sort(v.begin(), v.end());
  146. v.erase(unique(v.begin(), v.end()), v.end());
  147. int N = v.size();
  148. // cout<<" ** "<<endl;
  149. for(int i=; i<N; i++) {
  150. node.pb( getmin(v[i],v[i]));
  151. nv.pb(v[i]);
  152. if(i+ < N && v[i] + <= v[i+] - )
  153. {
  154. node.pb(getmin(v[i]+, v[i+]-));
  155. nv.pb(v[i]+);
  156. }
  157. }
  158.  
  159. /// 把一个开区间当成一个点。
  160.  
  161. N = nv.size();
  162. build(, N, );
  163. for(int i=; i<=q; i++) {
  164. if(ask[i].op == ) {
  165. update(getid(ask[i].le),getid(ask[i].ri), ask[i].x, , N, );
  166. }
  167. else {
  168. printf("%d\n",query(getid(ask[i].le), getid(ask[i].ri), , N, ));
  169. }
  170. }
  171. return ;
  172. }

CF803G - Periodic RMQ Problem 动态开点线段树 或 离线的更多相关文章

  1. Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

    思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 els ...

  2. 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树

    题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...

  3. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  4. codeforces 893F - Physical Education Lessons 动态开点线段树合并

    https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...

  5. HDU 6183 Color it(动态开点线段树)

    题目原网址:http://acm.hdu.edu.cn/showproblem.php?pid=6183 题目中文翻译: Time Limit: 20000/10000 MS (Java/Others ...

  6. [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)

    题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...

  7. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  8. codeforces 915E - Physical Education Lessons 动态开点线段树

    题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...

  9. CF915E Physical Education Lessons 动态开点线段树

    题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...

随机推荐

  1. 异常处理 _this.setData is not a function

    _this.setData is not a function;at api request success callback function TypeError: _this.setData is ...

  2. abp(net core)+easyui+efcore实现仓储管理系统——使用 WEBAPI实现CURD (十二)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  3. 集合(Collection解析 Set List Map三大集合运用)

    集合的概念:          集合是包含多个对象的简单对象,所包含的对象称为元素.集合里面可以包含任意多个对象,数量可以变化:同时对对象的类型也没有限制,也就是说集合里面的所有对象的类型可以相同,也 ...

  4. [ PyQt入门教程 ] PyQt5基本控件使用:消息弹出、用户输入、文件对话框

    本文主要介绍PyQt界面实现中常用的消息弹出对话框.提供用户输入的输入框.打开文件获取文件/目录路径的文件对话框.学习这三种控件前,先想一下它们使用的主要场景: 1.消息弹出对话框.程序遇到问题需要退 ...

  5. 自定义 EditText 样式

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  6. Selenium+java - 借助autolt完成上传文件操作

    写在前面: 上传文件是每个自动化测试同学会遇到,而且可以说是面试必考的问题,标准控件我们一般用sendkeys()就能完成上传,但是我们的测试网站的上传控件一般为自己封装的,用传统的上传已经不好用了, ...

  7. 已知词频生成词云图(数据库到生成词云)--generate_from_frequencies(WordCloud)

    词云图是根据词出现的频率生成词云,词的字体大小表现了其频率大小. 写在前面: 用wc.generate(text)直接生成词频的方法使用很多,所以不再赘述. 但是对于根据generate_from_f ...

  8. MobaXterm:远程终端登录软件封神选手

    提到SSH.Telnet等远程终端登录,我相信很多人想到的都是PuTTY PuTTY通常用于Windows,但实际上可以多平台运行,因此不表达为"Windows下的远程终端登录" ...

  9. C#的委托事件总结

    什么是委托?1.委托是C#中由用户自定义的一个类型.2.类表示的是数据和方法的集合,而委托实际上是一个能持有对某个或某些方法的引用的类.3.与其他的类不同,委托类能拥有一个签名,并且他只能持有与他的签 ...

  10. ibatis 核心原理解析

    最近查找一个生产问题的原因,需要深入研究 ibatis 框架的源码.虽然最后证明问题的原因与 ibatis 无关,但是这个过程加深了对 ibatis 框架原理的理解. 这篇文章主要就来讲讲 ibati ...