考试的时候被3100的评分吓住了,但其实这个评分有点虚高。
先来分析一下题面的要求:区间内加入至多 \(k\) 个数形成一个公差为 \(d\) 的等差数列
那么区间要满足一下条件:
-
所有数对 \(d\) 取模的值相等
-
没有重复的数
-
\((max-min+1)-(r-l+1)\le k\)
看着没有其它的选择,只能使用扫描线,前两个条件在扫描右端点的时候修改左端点的最小值即可,第三个条件可以转化成 \(w_l=max-min+l\le k+r\) 于是维护 \(w_l\) ,修改 \(max,min\) 可以使用单调栈,每次加入元素的时候就可以把 \(max,min\) 改变了的区间找出来进行修改,最后查询答案就直接在线段树上二分就可以了,注意 \(d=0\) 的特殊情况,这种情况就直接找最长连续段即可
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#pragma GCC optimeze(3)
#pragma GCC optimeze(2)
#define PII pair<int, int>
#define pb push_back
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define inv(x) (qpow(x,mod-2))
#define blong(i) ((i+K-1)/K)
using namespace std;
const int N=2e5+10;
const int M=3e5+5;
const int mod=9901;
double eps=1e-6;
inline int read(){char ch=getchar();bool f=0;int x=0;for(;!isdigit(ch);ch=getchar())if(ch=='-')f=1;for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);if(f==1)x=-x;return x;
}
unordered_map<int,int>lst;
int n,k,d,a[N],ansl=1,ansr=0,tr[N<<2],b[N<<2];
int stk1[N],stk2[N],top1,top2;
void pushup(int p){tr[p]=min(tr[p<<1],tr[p<<1|1]);
}
void pushdown(int p){if(b[p]){tr[p<<1]+=b[p],tr[p<<1|1]+=b[p],b[p<<1]+=b[p],b[p<<1|1]+=b[p],b[p]=0;}
}
void build(int p,int l,int r){if(l==r){tr[p]=l;return;}int mid=(l+r)>>1;build(p<<1,l,mid);build(p<<1|1,mid+1,r);pushup(p);
}
void change(int l,int r,int k,int p,int s,int t){if(s>=l&&t<=r){tr[p]+=k,b[p]+=k;return;}pushdown(p);int mid=(s+t)>>1;if(mid>=l)change(l,r,k,p<<1,s,mid);if(mid<r)change(l,r,k,p<<1|1,mid+1,t);pushup(p);
}
int query(int L,int R,int k,int p,int s,int t){if(s>R||t<L||tr[p]>k)return 0;if(s==t)return s;int mid=(s+t)>>1;pushdown(p);int x=query(L,R,k,p<<1,s,mid);return x? x:query(L,R,k,p<<1|1,mid+1,t);
}
signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>k>>d;for(int i=1;i<=n;i++)cin>>a[i],a[i]+=1e9;if(!d){for(int i=1;i<=n;i++){int l=i,r=i;while(r<=n&&a[r]==a[l])r++;if(a[r]!=a[l])r--;if(r-l>ansr-ansl)ansl=l,ansr=r;i=r;} cout<<ansl<<' '<<ansr;return 0;}build(1,1,n);int L=1;for(int i=1;i<=n;i++){if(a[i]%d==a[i-1]%d)L=max(L,lst[a[i]]+1);else L=i;lst[a[i]]=i;while(top1&&stk1[top1]>=L&&a[stk1[top1]]>a[i]){change(max(L,stk1[top1-1]+1),stk1[top1],a[stk1[top1]]/d,1,1,n);top1--;}change(max(L,stk1[top1]+1),i,-a[i]/d,1,1,n);stk1[++top1]=i;while(top2&&stk2[top2]>=L&&a[stk2[top2]]<a[i]){change(max(L,stk2[top2-1]+1),stk2[top2],-a[stk2[top2]]/d,1,1,n);top2--;}change(max(L,stk2[top2]+1),i,+a[i]/d,1,1,n);stk2[++top2]=i;int xx=query(L,i,i+k,1,1,n);if(xx){if(i-xx>ansr-ansl)ansl=xx,ansr=i;}}cout<<ansl<<" "<<ansr;return 0;
}