题目传送门: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)\):

#include <cstdio>
#include <algorithm> const int MN = 200005;
const int MS = 1 << 19 | 7; #define li (i << 1)
#define ri (i << 1 | 1)
#define mid ((l + r) >> 1)
#define ls li, l, mid
#define rs ri, mid + 1, r
int mn[MS], tg[MS];
inline void P(int i, int x) { mn[i] += x, tg[i] += x; }
inline void pd(int i) { if (tg[i]) P(li, tg[i]), P(ri, tg[i]), tg[i] = 0; }
void Build(int i, int l, int r) {
mn[i] = tg[i] = 0;
if (l == r) return ;
Build(ls), Build(rs);
}
void Mdf(int i, int l, int r, int a, int b, int x) {
if (r < a || b < l) return ;
if (a <= l && r <= b) return P(i, x);
pd(i), Mdf(ls, a, b, x), Mdf(rs, a, b, x);
mn[i] = std::min(mn[li], mn[ri]);
}
int Qur(int i, int l, int r, int a, int b, int x) {
if (r < a || b < l || mn[i] > x) return -1;
if (l == r) return l;
pd(i);
int lpos = Qur(ls, a, b, x);
return ~lpos ? lpos : Qur(rs, a, b, x);
} int Ans, MaxLen;
inline void Solve(int *A, int N, int K, int offset) {
if (N <= MaxLen) return ;
static int B[MN], C[MN], Lst[MN], stk1[MN], stk2[MN];
for (int i = 1; i <= N; ++i) B[i] = A[i];
std::sort(B + 1, B + N + 1);
int M = std::unique(B + 1, B + N + 1) - B - 1;
for (int i = 1; i <= N; ++i)
C[i] = std::lower_bound(B + 1, B + M + 1, A[i]) - B;
for (int i = 1; i <= M; ++i) Lst[i] = 0;
int MinL = 1, tp1 = 0, tp2 = 0;
Build(1, 1, N);
for (int i = 1; i <= N; ++i) {
MinL = std::max(MinL, Lst[C[i]] + 1);
Lst[C[i]] = i;
for (; tp1 && A[stk1[tp1]] <= A[i]; --tp1)
Mdf(1, 1, N, stk1[tp1 - 1] + 1, stk1[tp1], A[i] - A[stk1[tp1]]);
for (; tp2 && A[stk2[tp2]] >= A[i]; --tp2)
Mdf(1, 1, N, stk2[tp2 - 1] + 1, stk2[tp2], A[stk2[tp2]] - A[i]);
stk1[++tp1] = stk2[++tp2] = i;
Mdf(1, 1, N, i, i, i);
int lpos = Qur(1, 1, N, MinL, i, K + i);
if (~lpos && MaxLen < i - lpos + 1) {
MaxLen = i - lpos + 1;
Ans = lpos + offset;
}
}
} int N, K, D;
int A[MN], R[MN], B[MN], t; int main() {
scanf("%d%d%d", &N, &K, &D);
for (int i = 1; i <= N; ++i) scanf("%d", &A[i]);
if (D == 0) {
int mxl = 1, lst = A[1], len = 1, ans = 1;
for (int i = 2; i <= N; ++i) {
if (A[i] == lst) ++len;
else len = 1, lst = A[i];
if (len > mxl) mxl = len, ans = i - mxl + 1;
}
printf("%d %d\n", ans, ans + mxl - 1);
return 0;
}
for (int i = 1; i <= N; ++i) R[i] = (A[i] % D + D) % D;
for (int i = 1; i <= N; ++i) {
B[++t] = (A[i] - R[i]) / D;
if (i == N || R[i] != R[i + 1])
Solve(B, t, K, i - t), t = 0;
}
printf("%d %d\n", Ans, Ans + MaxLen - 1);
return 0;
}

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. mod35云掩膜产品用法

    在网上一直没找到一个明确说怎么用MOD35产品的,都是说去看用户手册,第一次看了过一段时间我又忘记怎么搞了,赶紧记下来. 而且现在才发现第一次自己搞的都弄错了. 简单的判断是否是云,只要读取mod35 ...

  2. 【操作系统之十五】iptables黑白名单、自定义链、网络防火墙、常用动作

    1.黑白名单当链的默认策略为ACCEPT时,链中的规则对应的动作应该为DROP或者REJECT,表示只有匹配到规则的报文才会被拒绝,没有被规则匹配到的报文都会被默认接受,这就是"黑名单&qu ...

  3. Intellij插件之MavenHelper

    作用: 一键查看maven依赖,查看冲突的依赖,一键进行exclude依赖 插件提供地址: https://plugins.jetbrains.com/plugin/7179-maven-helper ...

  4. (四)golang--注意事项

    以.go为结尾: 执行入口是main()函数: 区分大小写: Go方法由一条条语句构成,每个语句后不需要加问号: Go编译器是一行行进行编译的,一行不能写多条语句: go语言定义的变量或者import ...

  5. pytorch_05_神经网络

    神经网络 一些神经元的输出会变成另外一些神经元的输入,一般以层来组织,最常见的是全连接神经网络,其中两个相邻层中每一个层的所有神经元与另一个层的所有神经元相连,每个层内部的神经元不相连. 一般的,N层 ...

  6. Go gRPC 调试工具

    概述 最近这段时间工作挺忙的,发现已经 3 周没更文了... 感谢你们还在,今天给大家分享一款 gRPC 的调试工具. 进入正题. 当我们在写 HTTP 接口的时候,使用的是 Postman 进行接口 ...

  7. [转帖]编写shell脚本所需的语法和示例

    编写shell脚本所需的语法和示例 https://blog.csdn.net/CSDN___LYY/article/details/100584638 在说什么是shell脚本之前,先说说什么是sh ...

  8. R语言dai xie

    R语言,Python长期招代写,作业量充足,需要一定英文能力,价格满意.有意者请留言联系,谢谢

  9. Java面试-TCP连接及其优化

    作为一个后端程序员,网络连接这块是一个绕不过的砍,当你在做服务器优化的时候,网络优化也是其中一环,那么作为网络连接中最基础的部分-TCP连接你了解吗?今天我们来仔细看看这个部分. TCP建立连接-三次 ...

  10. 用友U9 刷新当前页面代码

    this.Action.NavigateAction.Refresh(null, true);//刷新当前页