题目传送门:CF407E

题意简述:

给定非负整数 \(k,d\) 和一个长度为 \(n\)(\(1\le n\le 2\times 10^5\))的整数序列 \(a\)。

求这个序列中最长的一个连续子串 \(a[l:r]\) 满足:添加不超过 \(k\) 个整数,再排序后,可以形成公差为 \(d\) 的等差数列。

若有多个满足条件取最左侧的那个。

题解:

首先特判 \(d=0\) 的情况,这时相当于求最长连续段。

易发现若一些数要组成一个公差为 \(d\) 的等差数列,必须要满足这些数模 \(d\) 同余。

所以依次考虑每个模 \(d\) 同余的连续子串,将其中每个数除以 \(d\) 向下取整,转化为 \(d=1\) 的情况。

转化为一个经典问题,要求连续子串的值域满足某些条件,而条件仅和子串中的最值、子串端点的位置有关。

假设子串为 \(a[l:r]\),这里的条件是:\(\max\{a[l:r]\}-\min\{a[l:r]\}+l\le k+r\) 且 \(a[l:r]\) 中无重复元素。

考虑右端点 \(r\) 从 \(1\) 开始逐步向右推,每次求出最佳的合法左端点位置。

对于两个限制,前者使用两个单调栈和线段树解决,后者限定了一个 \(l\) 的下限,维护每个值的上一次出现位置,每次向右推时更新即可。

求位置时需要查询一段区间内的最靠左的值 \(\le k+r\) 的位置,这可以通过线段树维护最小值简单地做到。

下面是代码,时间复杂度 \(\mathcal{O}(n\log n)\):

  1. #include <cstdio>
  2. #include <algorithm>
  3. const int MN = 200005;
  4. const int MS = 1 << 19 | 7;
  5. #define li (i << 1)
  6. #define ri (i << 1 | 1)
  7. #define mid ((l + r) >> 1)
  8. #define ls li, l, mid
  9. #define rs ri, mid + 1, r
  10. int mn[MS], tg[MS];
  11. inline void P(int i, int x) { mn[i] += x, tg[i] += x; }
  12. inline void pd(int i) { if (tg[i]) P(li, tg[i]), P(ri, tg[i]), tg[i] = 0; }
  13. void Build(int i, int l, int r) {
  14. mn[i] = tg[i] = 0;
  15. if (l == r) return ;
  16. Build(ls), Build(rs);
  17. }
  18. void Mdf(int i, int l, int r, int a, int b, int x) {
  19. if (r < a || b < l) return ;
  20. if (a <= l && r <= b) return P(i, x);
  21. pd(i), Mdf(ls, a, b, x), Mdf(rs, a, b, x);
  22. mn[i] = std::min(mn[li], mn[ri]);
  23. }
  24. int Qur(int i, int l, int r, int a, int b, int x) {
  25. if (r < a || b < l || mn[i] > x) return -1;
  26. if (l == r) return l;
  27. pd(i);
  28. int lpos = Qur(ls, a, b, x);
  29. return ~lpos ? lpos : Qur(rs, a, b, x);
  30. }
  31. int Ans, MaxLen;
  32. inline void Solve(int *A, int N, int K, int offset) {
  33. if (N <= MaxLen) return ;
  34. static int B[MN], C[MN], Lst[MN], stk1[MN], stk2[MN];
  35. for (int i = 1; i <= N; ++i) B[i] = A[i];
  36. std::sort(B + 1, B + N + 1);
  37. int M = std::unique(B + 1, B + N + 1) - B - 1;
  38. for (int i = 1; i <= N; ++i)
  39. C[i] = std::lower_bound(B + 1, B + M + 1, A[i]) - B;
  40. for (int i = 1; i <= M; ++i) Lst[i] = 0;
  41. int MinL = 1, tp1 = 0, tp2 = 0;
  42. Build(1, 1, N);
  43. for (int i = 1; i <= N; ++i) {
  44. MinL = std::max(MinL, Lst[C[i]] + 1);
  45. Lst[C[i]] = i;
  46. for (; tp1 && A[stk1[tp1]] <= A[i]; --tp1)
  47. Mdf(1, 1, N, stk1[tp1 - 1] + 1, stk1[tp1], A[i] - A[stk1[tp1]]);
  48. for (; tp2 && A[stk2[tp2]] >= A[i]; --tp2)
  49. Mdf(1, 1, N, stk2[tp2 - 1] + 1, stk2[tp2], A[stk2[tp2]] - A[i]);
  50. stk1[++tp1] = stk2[++tp2] = i;
  51. Mdf(1, 1, N, i, i, i);
  52. int lpos = Qur(1, 1, N, MinL, i, K + i);
  53. if (~lpos && MaxLen < i - lpos + 1) {
  54. MaxLen = i - lpos + 1;
  55. Ans = lpos + offset;
  56. }
  57. }
  58. }
  59. int N, K, D;
  60. int A[MN], R[MN], B[MN], t;
  61. int main() {
  62. scanf("%d%d%d", &N, &K, &D);
  63. for (int i = 1; i <= N; ++i) scanf("%d", &A[i]);
  64. if (D == 0) {
  65. int mxl = 1, lst = A[1], len = 1, ans = 1;
  66. for (int i = 2; i <= N; ++i) {
  67. if (A[i] == lst) ++len;
  68. else len = 1, lst = A[i];
  69. if (len > mxl) mxl = len, ans = i - mxl + 1;
  70. }
  71. printf("%d %d\n", ans, ans + mxl - 1);
  72. return 0;
  73. }
  74. for (int i = 1; i <= N; ++i) R[i] = (A[i] % D + D) % D;
  75. for (int i = 1; i <= N; ++i) {
  76. B[++t] = (A[i] - R[i]) / D;
  77. if (i == N || R[i] != R[i + 1])
  78. Solve(B, t, K, i - t), t = 0;
  79. }
  80. printf("%d %d\n", Ans, Ans + MaxLen - 1);
  81. return 0;
  82. }

CodeForces 407E: k-d-sequence的更多相关文章

  1. Codeforces 486E LIS of Sequence(线段树+LIS)

    题目链接:Codeforces 486E LIS of Sequence 题目大意:给定一个数组.如今要确定每一个位置上的数属于哪一种类型. 解题思路:先求出每一个位置选的情况下的最长LIS,由于開始 ...

  2. Codeforces GYM 100114 C. Sequence 打表

    C. Sequence Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description ...

  3. CodeForces 670E Correct Bracket Sequence Editor(list和迭代器函数模拟)

    E. Correct Bracket Sequence Editor time limit per test 2 seconds memory limit per test 256 megabytes ...

  4. Codeforces gym102152 K.Subarrays OR

    传送:http://codeforces.com/gym/102152/problem/K 题意:给定$n(n\le10^5)$个数$a_i(a_i\le10^9)$,对于任一个子数组中的数进行或操作 ...

  5. Codeforces 670E - Correct Bracket Sequence Editor - [线段树]

    题目链接:https://codeforces.com/contest/670/problem/E 题意: 给出一个已经匹配的括号串,给出起始的光标位置(光标总是指向某个括号). 有如下操作: 1.往 ...

  6. 【codeforces 623E】 Transforming Sequence

    http://codeforces.com/problemset/problem/623/E (题目链接) 题意 长度为${n}$的满足前缀按位或为单调递增的${k}$位序列.要求每个位置为${[1, ...

  7. codeforces 1133E K Balanced Teams

    题目链接:http://codeforces.com/contest/1133/problem/E 题目大意: 在n个人中找到k个队伍.每个队伍必须满足最大值减最小值不超过5.求满足条件k个队伍人数的 ...

  8. codeforces C. Cows and Sequence 解题报告

    题目链接:http://codeforces.com/problemset/problem/284/C 题目意思:给出3种操作:t = 1:在前 a 个数中每个数都加上x: t= 2:在数组末尾增加一 ...

  9. 【codeforces 602D】Lipshitz Sequence

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  10. Codeforces 1133E - K Balanced Teams - [DP]

    题目链接:https://codeforces.com/contest/1133/problem/C 题意: 给出 $n$ 个数,选取其中若干个数分别组成 $k$ 组,要求每组内最大值与最小值的差值不 ...

随机推荐

  1. [LeetCode] 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加

    Given a string S of '(' and ')' parentheses, we add the minimum number of parentheses ( '(' or ')', ...

  2. [LeetCode] 829. Consecutive Numbers Sum 连续数字之和

    Given a positive integer N, how many ways can we write it as a sum of consecutive positive integers? ...

  3. [LeetCode] 55. Jump Game 跳跃游戏

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  4. [LeetCode] 10. Regular Expression Matching 正则表达式匹配

    Given an input string (s) and a pattern (p), implement regular expression matching with support for  ...

  5. 文件夹如何添加备注(保证可以WIN7 WIN10测试通过)

    网上很多方法都有人说试过了,不可以.其实不是不可以,他们都没有说完整 今天自己弄了下,弄出来了,废话不多说先上图 如果需要用备注排序,那么就需要把排序的选项加上备注的分类 1.获得desktop.in ...

  6. mysq-5.7忘记密码修改

    一,停止mysql /etc/init.d/mysqld stop 二,启动mysql mysqld_safe --skip-grant-tables 安全模式+免验证启动服务 三,登入mysql服务 ...

  7. 推荐一款移动端小视频App玲珑视频

    推荐一款移动端小视频App玲珑视频 一 应用描述 玲珑小视频,边看边聊![海量视频,刷个不停,还能找妹子语音聊天哦][随手拍一拍,记录美好生活,还能拿金币哦][看视频领金币.登录领金币.拍视频领金币. ...

  8. Helm 常用命令及操作

    Helm 常用命令 查看版本 #helm version 查看当前安装的charts #helm list 查询 charts #helm search redis 安装charts #helm in ...

  9. Java 性能调优小技巧

    1.在知道必要之前不要优化系统 这可能是最重要的性能调整技巧之一.你应该遵循常见的最佳实践做法并尝试高效地实现用例.但是,这并不意味着在你证明必要之前,你应该更换任何标准库或构建复杂的优化. 在大多数 ...

  10. Mysql 生成不重复的随机数字

    在网上查找Mysql 生成不重复的随机数字 ,竟然没找到合适的例子. 其实思路很简单,利用MySQL现有的函数,然后进行加工处理,达到预期的结果.可以用到的MySQL函数为rand() ,以及 rou ...