[暴力][线段树] Jzoj P4527 数列

Description

 

Input

Output

 

Sample Input

6 1 2
4 3 2 8 6 2

Sample Output

3 5
 

Data Constraint

题解

  • 这题又可以水,对我这种懒人来说十分快乐 N^2过十万没什么好说的
  • 下面讲讲正解,正解是线段树
  • 首先我们先来看看对于一个满足要求的区间有什么条件:
  • ①不存在相同的数
  • ②所有的数在模d的意义下同余
  • ③设max为区间最大值,min为区间最小值,应该满足:(maxmin)/d(ij)<=
  • 这些应该都比较显然,就不解释了
  • 我们可以先将在模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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/11127449.html
今日推荐