随机

随机

发现当端点值差最小时本区间一定不可以更新,所以最终答案一定是一段端点价值差最小的区间
本题类似分治的做法,可以先将子区间的答案算出来,然后对于穿过mid的部分,我们只需要找到差比ans小的,记录下来,可更新的答案一定在这些点之间,然后枚举更新即可。

#include
using namespace std;

const int N=2e6+5;
int n,a[N];
struct node{
	int x,y;
}q[N],tmp[N];
int val(node a,node b){
	return max(abs(b.y-a.y)+1,abs(a.x-b.x));
}
bool cmp(node a,node b){
	return a.x<b.x;
}
int get(int l,int r){
	if(l==r) return N*5;
	if(r==l+1) return max(2,abs(q[l].x-q[r].x));
	int mid=((l+r)>>1);
	int mn=N*5;
	mn=min(mn,get(l,mid));
	mn=min(mn,get(mid+1,r));
	int cnt=0;
	for(int i=l;i<=mid;i++){
		if(abs(q[mid].y-q[i].y)<mn)tmp[++cnt].x=q[i].x,tmp[cnt].y=q[i].y;
	}
	for(int i=mid+1;i<=r;i++){
		if(abs(q[i].y-q[mid+1].y)<mn)tmp[++cnt].x=q[i].x,tmp[cnt].y=q[i].y;
		else break;
	}
	sort(tmp+1,tmp+cnt+1,cmp);
	for(int i=1;i<=cnt;i++)
	for(int j=i+1;j<=cnt&&(abs(tmp[j].x-tmp[i].x)<=mn);j++){
		mn=min(mn,val(tmp[i],tmp[j]));
	}
	return mn;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		q[i].x=a[i],q[i].y=i;
	}
	printf("%d",get(1,n));
}

你可能感兴趣的:(例题,分治)