CF407E k-d-sequence

一段子区间为 k-d-sequence,等价于满足 \(\mod d\) 同余,且所有数整除 \(d\) 排序后 \(\max-\min-r+l\le k\) 表示能通过插入 \(k\) 个数使其值域连续。

第一个限制不好在扫描线中处理,直接将原序列分为很多段极长同余段,每段内扫描线即可。

第二种限制,将 \(\max-\min-r+l\le k\to \max-\min+l\le r+k\),则以 \(r\) 扫描线,维护每个位置的 \(\max-\min+l\),这是可以用单调栈与线段树简单维护的,查询相当于找到最小的位置满足该不等式限制,线段树二分即可。复杂度 \(O(n\log n)\)

特殊的,若 \(d=0\) 则无法 \(\mod d\),但此时等价于找到最长的相同字段,随便 \(O(n)\) 做。

Takanashi Rikka
// Problem: CF407E k-d-sequence
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF407E
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define intz(x,z) memset((x),(z),sizeof((x)))
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
inline ll lowbit(ll x){return x&-x;}
#define fi first
#define se second
inline void cmx(auto &x,ll y){if(y>x)x=y;}
inline void cmn(auto &x,ll y){if(y<x)x=y;}
const int N=2e5+5;
#define int ll
int a[N],x[N],X,y[N],Y;
unordered_map<int,int>p;
struct node{int l,r,x,laz;}t[N<<2];
void build(int u,int l,int r){
	t[u]={l,r};if(l==r)return;int mid=l+r>>1;
	build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
void add(int u,int x){t[u].x+=x,t[u].laz+=x;}
void pd(int u){add(u<<1,t[u].laz),add(u<<1|1,t[u].laz),t[u].laz=0;}
void pushup(int u){t[u].x=min(t[u<<1].x,t[u<<1|1].x);}
void upd(int u,int l,int r,int x){
	if(t[u].l>=l&&t[u].r<=r)return add(u,x);
	int mid=t[u].l+t[u].r>>1;pd(u);
	if(l<=mid)upd(u<<1,l,r,x);if(r>mid)upd(u<<1|1,l,r,x);
	pushup(u);
}
int query(int u,int l,int r,int x){
	if(t[u].r<l||t[u].l>r||t[u].x>x)return -1;
	if(t[u].l==t[u].r)return t[u].l;
	pd(u);int res=query(u<<1,l,r,x);
	if(res!=-1)return res;
	return query(u<<1|1,l,r,x);
}
int ask(int u,int x){
	if(t[u].l==t[u].r)return t[u].x;
	int mid=t[u].l+t[u].r>>1;pd(u);
	return ask((x<=mid?u<<1:u<<1|1),x); 
}
void UesugiErii(){
	int n,k,d;cin>>n>>k>>d;
	for(int i=1;i<=n;i++)cin>>a[i],a[i]+=1e9;
	if(!d){
		int lst=1,al=1,ar=1;
		for(int i=2;i<=n;i++)
			if(a[i]^a[i-1]){
				if(i-lst>ar-al+1)
					al=lst,ar=i-1;
				lst=i;
			}
		return cout<<al<<' '<<ar,void();
	} 
	int lst=1,al=1,ar=1;
	build(1,1,n);
	for(int i=2;i<=n+1;i++)
		if(i==n+1||(a[i]%d!=a[i-1]%d)){
			for(int j=lst;j<i;j++)a[j]/=d;
			X=Y=0;p.clear();
			int L=lst;
			for(int j=lst;j<i;j++){
				if(p.count(a[j]))cmx(L,p[a[j]]+1);p[a[j]]=j;
				while(X&&a[x[X]]<a[j])upd(1,x[X-1]+1,x[X],-a[x[X]]),--X;
				while(Y&&a[y[Y]]>a[j])upd(1,y[Y-1]+1,y[Y],a[y[Y]]),--Y;
				x[++X]=y[++Y]=j;
				upd(1,x[X-1]+1,j,a[j]),upd(1,y[Y-1]+1,j,-a[j]),upd(1,j,j,j);
				int l=query(1,L,j,j+k);
				if(l!=-1&&j-l+1>ar-al+1)ar=j,al=l;
			}
			lst=i;
		}
	cout<<al<<' '<<ar<<'\n';
}
signed main(){
	//cfast;
	int _=1;//cin>>_;
	for(;_;_--)UesugiErii();
	return 0;
}
posted @ 2025-12-23 11:11  Uesugi1  阅读(4)  评论(0)    收藏  举报