题解
- 这题又可以水,对我这种懒人来说十分快乐 N^2过十万没什么好说的
- 下面讲讲正解,正解是线段树
- 首先我们先来看看对于一个满足要求的区间有什么条件:
- ①不存在相同的数
- ②所有的数在模d的意义下同余
- ③设max为区间最大值,min为区间最小值,应该满足:(max−min)/d−(i−j)<=k
- 这些应该都比较显然,就不解释了
- 我们可以先将在模d意义下同余的一段区间给弄出来
- 然后每句右端点
- 如果在同一个区间,维护左边的那个值的区间最小值
对于一个右端点可以影响到的位置,这个就可以用单调栈预处理最为最大最小值会影响到的位置
代码
1 #include <cstdio>
2 #include <iostream>
3 #define ll long long
4 using namespace std;
5 const int mo=19260817,N=2e5+10,p=37;
6 int n,k,d,l,r,pos,ans,a[N],pre[N],hash[mo+1][2];
7 int calc(ll x,int d)
8 {
9 ll r=(x*p%mo+mo)%mo+1,s;
10 while (hash[r][0]&&hash[r][0]^x) r=r%mo+1;
11 hash[r][0]=x,s=hash[r][1],hash[r][1]=d;
12 return s;
13 }
14 int main()
15 {
16 scanf("%d%d%d",&n,&k,&d);
17 for (int i=1;i<=n;i++) scanf("%d",&a[i]),pre[i]=calc(a[i],i);
18 for (int i=1;i<n;i++)
19 {
20 l=r=a[i];
21 for (int j=i+1;j<=n;j++)
22 {
23 if (pre[j]&&i<=pre[j]) break;
24 if ((a[j]-a[i])%d) break;
25 l=max(l,a[j]),r=min(r,a[j]);
26 if ((l-r)/d-(j-i)<=k) if (j-i+1>ans) ans=j-i+1,pos=i; else if (j-i+1==ans&&i<pos) pos=i;
27 }
28 }
29 printf("%d %d",pos,pos+ans-1);
30 }