题意:给定$a_{1\cdots n}$,让你求出一个最长的子串$a_{l\cdots r}$,使得这个子串加上最多$k$个数字并排序后是一个公差为$d$的等差数列

首先$d=0$就是最长连续相等段,扫一遍解决

然后显然$a_{l\cdots r}$都是模$d$同余的,我们不妨对模$d$的余数不同的段分开处理

把每个数先$+10^9$(让它变为非负)再除以$d$,转化为$d=1$的问题

那么题目的限制条件就是$\mathop\max\limits_{i=l}^ra_i-\mathop\min\limits_{i=l}^ra_i+1\leq r-l+1+k$且$a_{l\cdots r}$中没有重复元素

所以整个算法的大致思路就是,对$a_{l\cdots r}$,从大到小枚举$i\in[l,r]$,找到最大的$j\in[l,r]$满足$\mathop\max\limits_{k=i}^ja_k-\mathop\min\limits_{k=i}^ja_k-r\leq k-l$且$a_{i\cdots j}$中没有相同元素

没有相同元素:直接用一个map存每个数上一次出现的位置,相应左移$r$即可

对于这个不等式,注意到$f(r)=\mathop\max\limits_{i=l}^ra_i$是单调不减的,所以我们可以用一个单调栈存当前区间内对于不同的$j$,对上式有贡献的$a_i$(即从左往右扫,会令当前最大值变化的那些$a_i$),$\min$同理,当左端点移动时,入栈出栈的同时用线段树维护$\max-\min$即可,对于$-r$,建线段树时第$i$位的初值赋为$-i$即可,我们只需要在线段树上二分找到最右的$\leq k-i$的值即可

#include<stdio.h>
#include<map>
using namespace std;
int mn[800010],ad[800010];
void add(int x,int v){
	mn[x]+=v;
	ad[x]+=v;
}
void pushdown(int x){
	if(ad[x]){
		add(x<<1,ad[x]);
		add(x<<1|1,ad[x]);
		ad[x]=0;
	}
}
void pushup(int x){mn[x]=min(mn[x<<1],mn[x<<1|1]);}
void build(int l,int r,int x){
	if(l==r){
		mn[x]=-l;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,x<<1);
	build(mid+1,r,x<<1|1);
	pushup(x);
}
void modify(int L,int R,int v,int l,int r,int x){
	if(L<=l&&r<=R)return add(x,v);
	pushdown(x);
	int mid=(l+r)>>1;
	if(L<=mid)modify(L,R,v,l,mid,x<<1);
	if(mid<R)modify(L,R,v,mid+1,r,x<<1|1);
	pushup(x);
}
int query(int L,int R,int v,int l,int r,int x){
	if(mn[x]>v)return 0;
	if(l==r)return l;
	pushdown(x);
	int mid=(l+r)>>1,res;
	if(R>mid){
		res=query(L,R,v,mid+1,r,x<<1|1);
		if(res)return res;
	}
	if(L<mid){
		res=query(L,R,v,l,mid,x<<1);
		if(res)return res;
	}
	return 0;
}
map<int,int>pos;
int a[200010],s1[200010],s2[200010],n,k,d,t1,t2,L,R;
void solve(int l,int r){
	if(l==r)return;
	int i,tr,res;
	for(i=l;i<=r;i++)a[i]=a[i]/d+1;
	tr=r+1;
	pos.clear();
	t1=t2=0;
	s1[0]=s2[0]=r+1;
	for(i=r;i>=l;i--){
		if(pos.count(a[i]))tr=min(tr,pos[a[i]]);
		while(t1&&a[i]>a[s1[t1]]){
			modify(s1[t1],s1[t1-1]-1,-a[s1[t1]],1,n,1);
			t1--;
		}
		t1++;
		s1[t1]=i;
		modify(s1[t1],s1[t1-1]-1,a[i],1,n,1);
		while(t2&&a[i]<a[s2[t2]]){
			modify(s2[t2],s2[t2-1]-1,a[s2[t2]],1,n,1);
			t2--;
		}
		t2++;
		s2[t2]=i;
		modify(s2[t2],s2[t2-1]-1,-a[i],1,n,1);
		res=query(i,tr-1,k-i,1,n,1);
		if(res-i>R-L||(res-i==R-L&&i<L)){
			L=i;
			R=res;
		}
		pos[a[i]]=i;
	}
}
int main(){
	int i,l,r;
	scanf("%d%d%d",&n,&k,&d);
	for(i=1;i<=n;i++){
		scanf("%d",a+i);
		a[i]+=1000000000;
	}
	L=R=1;
	if(d==0){
		for(l=1;l<=n;l=r){
			for(r=l;r<=n&&a[r]==a[l];r++);
			if(r-l>R-L+1){
				L=l;
				R=r-1;
			}
		}
		printf("%d %d",L,R);
		return 0;
	}
	build(1,n,1);
	L=R=1;
	for(l=1;l<=n;l=r){
		for(r=l;r<=n&&a[l]%d==a[r]%d;r++);
		solve(l,r-1);
	}
	printf("%d %d",L,R);
}

[CF407E]k-d-sequence的更多相关文章

  1. 【dfs】Sequence Decoding

    Sequence Decoding 题目描述 The amino acids in proteins are classified into two types of elements, hydrop ...

  2. Gym 100703G---Game of numbers(DP)

    题目链接 http://vjudge.net/contest/132391#problem/G Description standard input/outputStatements — It' s ...

  3. 转:Python获取随机数(中文)

    下面介绍下random中常见的函数. 前提:需要导入random模块 >>>import random 1.random.random random.random() 用于生成一个0 ...

  4. Qt4--加密日记本(子例化QMainWindow文本加密解密)

    近来刚学习Qt4编程,想找个实例练习练习,于是产生了一个想法,就是怎么样做一个文本加密,这样,自己保存的一些文档可以通过软件 生成加密文本,到时候要看的时候,通过自己的软件读取就可以.既然有想法了,那 ...

  5. python随机数

    前提:需要导入random模块 >>>import random 1.random.random random.random()用于生成一个0到1的随机符小数: 0 <= n ...

  6. 关于python 模块导入

    如何将自己写的库加入到python的库路径中: 首先查看python包含的库路径,步骤如下: a.打开python命令界面 b.import  sys    c.sys.path 1.在python安 ...

  7. 剑指Offer 23. 二叉搜索树的后序遍历序列 (二叉搜索树)

    题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 题目地址 https://www.nowcoder ...

  8. 开发笔记:python与随机数(转)

    这些天需要用到从一堆数中随机提取几个数,于是重新研究了下random模块. 下面介绍下random中常见的函数. 前提:需要导入random模块 >>>import random 1 ...

  9. Leetcode 413. Arithmetic Slice 算术序列切片(动态规划,暴力)

    Leetcode 413. Arithmetic Slice 算术序列切片(动态规划,暴力) 题目描述 如果一个数组1.至少三个元素2.两两之间差值相同,那么这个数组就是算术序列 比如下面的数组都是算 ...

  10. python随机数的产生

    导入 random模块  >>> import random 1.  random.random random.random()用于生成一个0到1的随机浮点数: 0 <= n ...

随机推荐

  1. 移动端H5滚动穿透解决方案

    最近遇到一个很 巨恶心的问题  ios10下面 页面弹窗有滚动穿透问题 各种google 终于找到了答案,但是体验还不是很好,基本能忍受 废话不多说,上方法 最后终于想到一个处理方案,就是第一种方案的 ...

  2. [hdu 2102]bfs+注意INF

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 感觉这个题非常水,结果一直WA,最后发现居然是0x3f3f3f3f不够大导致的……把INF改成I ...

  3. js用for of 遍历数组

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. tomcat 配置文件中设置JAVA_HOME

    Tomcat默认情况下会用系统的环境变量中找到JAVA_HOME和JRE_HOME.但是有的时候我们需要不同版本的JDK共存. 可以在${TOMCAT_HOME}/bin/setclasspath.b ...

  5. linux编译动态库 fPIC作用

    在生成动态库时,常常习惯性的加上fPIC选项,fPIC有什么作用和意义,加不加有什么区别,这里做下小结: fPIC的全称是 Position Independent Code, 用于生成位置无关代码. ...

  6. HDU 2105 The Center of Gravity (数学)

    题目链接 Problem Description Everyone know the story that how Newton discovered the Universal Gravitatio ...

  7. hashlib,suprocess,configparser模块

    十 hashlib模块 1.什么叫hash:hash是一种算法,该算法接受传入的内容,经过运算得到一串hash值 2.hash值的特点是: 2.1 只要传入的内容一样,得到的hash值必然一样==== ...

  8. [Leetcode Week3]Clone Graph

    Clone Graph题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/clone-graph/description/ Description Clon ...

  9. Codeforces 106 DIV2 ACD

    B表示完全看不懂..就不弄了.. E字符串先不管了.到时候系统学下字符串再处理 A #include <map> #include <set> #include <lis ...

  10. 电脑IP总是变的问题

    如题,如何解决该问题? 右键---->个性化---->更改桌面图标---->添加网络图标 右键网络图标----->属性---->更改适配器设置---->右键属性,找 ...