CodeForces - 1169C(二分+思维)

CodeForces - 1169C

 

1、思路:

每次可以选取任意几个数字进行(ai+1)%m的操作,所以最多m次让序列变为非递减序列。

让所有的元素值保持尽可能的小,能使最终的操作数最小。

所以可以二分查找需要进行修改的次数tim。

 

2、代码:

#include
#include
#include
#include
using namespace std;
const int maxn = 3e5+10;
int n,m,a[maxn];
bool pd(int tim){
	int pre;
	//在修改次数确定的前提下,让每个元素变的最小 
	if(a[1]+tim>=m) pre = 0;//如果操作数可以让a1变为0,就让a1变为0(最小) 
	else pre = a[1]; //不能变为0,保持原来的值即是最小 
	for(int i=2;i<=n;i++){
		int tmp = -1;
		if(a[i]+tim>=m&&(a[i]+tim)%m>=pre) tmp = pre; //如果当前元素可以变得与上一个元素一样,就变为一样 
		else if(a[i]<=pre&&a[i]+tim>=pre) tmp = pre; //当前元素变为与上一个元素相同 
		else if(a[i]>pre) tmp = a[i]; //当前元素大于上一个元素,且之前的+1%m操作只会让它变大,就不用修改 
		if(tmp==-1) return false; //所有操作失效,在当前次数下不能变为非递增序列 
		pre = tmp;
	}
	return true;
}
int main(void){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	int l = 0,r = m,ans = 0;
	while(l<=r){
		int mid = (l+r)>>1;
		if(pd(mid)){
			ans = mid;
			r = mid-1;
		}
		else l = mid+1;
	}
	printf("%d\n",ans);
	return 0;
}

 

你可能感兴趣的:(二分优化,codeforce)