百折不挠|

Xdik

园龄:1个月粉丝:7关注:24

「CF407E」k-d-sequence

考试的时候被3100的评分吓住了,但其实这个评分有点虚高。

先来分析一下题面的要求:区间内加入至多 k 个数形成一个公差为 d 的等差数列

那么区间要满足以下条件:

  • 所有数对 d 取模的值相等

  • 没有重复的数

  • (maxmin+1)(rl+1)k

看着没有其它的选择,只能使用扫描线,前两个条件在扫描右端点的时候修改左端点的最小值即可,第三个条件可以转化成 wl=maxmin+lk+r 于是维护 wl ,修改 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;
}

本文作者:Xdik

本文链接:https://www.cnblogs.com/Xdik/p/18712726

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Xdik  阅读(9)  评论(2编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起