[UOJ206]Gap

子任务$1$:直接找到最大值后从两边开始找,一步一步从左右到中间确定所有数,调用次数是$\left\lceil\dfrac n2\right\rceil$

子任务$2$:先找到最大值$mx$和最小值$mn$,代价为$N+1$,令$L=\left\lceil\dfrac{mx-mn}{N-1}\right\rceil$,那么答案$\geq L$

我们把整个序列按权值分成许多大小为$L$的块,那么答案一定跨块,所以直接对每块调用然后用上次的最大值和这次的最小值更新答案即可,最多调用$N-1$次,总共包含$N$个数,所以总代价$\leq3N$,刚好满足题目的要求

#include<stdio.h>
#include"gap.h"
typedef long long ll;
const ll inf=1e18;
ll a[100010];
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
ll up(ll a,ll b){return a%b!=0?a/b+1:a/b;}
ll findGap(int T,int N){
	if(T==1){
		int i;
		ll ans;
		a[0]=-1;
		a[N+1]=inf+1;
		for(i=1;i<=(N+1)>>1;i++)MinMax(a[i-1]+1,a[N-i+2]-1,a+i,a+N-i+1);
		ans=0;
		for(i=1;i<N;i++)ans=max(ans,a[i+1]-a[i]);
		return ans;
	}else{
		ll i,mn,mx,t1,t2,las,L,ans;
		MinMax(0,inf,&mn,&mx);
		L=up(mx-mn,N-1);
		las=-1;
		ans=L;
		for(i=mn;i<=mx;i+=L+1){
			MinMax(i,min(i+L,mx),&t1,&t2);
			if(las!=-1)ans=max(ans,t1-las);
			if(t2!=-1)las=t2;
		}
		return ans;
	}
}

猜你喜欢

转载自www.cnblogs.com/jefflyy/p/9126995.html
GAP
GAP
206