1、思路:
每次可以选取任意几个数字进行(ai+1)%m的操作,所以最多m次让序列变为非递减序列。
让所有的元素值保持尽可能的小,能使最终的操作数最小。
所以可以二分查找需要进行修改的次数tim。
2、代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
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;
}