给个数组a和模数m,进行n次操作让这个数组变为不降序列,每次操作可以选择数组中顺序的k个a[i],并将其替换为(a[i]+1)%m。
思路:首先进行的操作不超过m次,如果用了m次,那么(a[i]+m)%m还是a[i],没用,因此从0到m进行二分查找次数,对于每个次数检验能否让该序列不降。
#include <bits/stdc++.h>
#include <vector>
using namespace std;
const int SIZE=3e5+5;
int n,M,ans;
vector<int>a;
void Input()
{
cin>>n>>M;
a.push_back(0);
for(int i=1,tmp;i<=n;i++)
{
cin>>tmp;
a.push_back(tmp);
}
}
void Binary()
{
int l=0,r=M,flag,mid;
while(l<=r)
{
flag=1;
mid=(l+r)/2;
for(int i=1,pre=0;i<=n;i++) //pre保存要检查的数的前面一个,因为二分有个while循环,所以不直接用a[i-1]
{
if(a[i]+mid<M) //如果经过mid次操作后这个数没有超过模数M,因为操作可以少于mid所以操作后得到的数是个范围,此时为a[i]~a[i]+mid
{
if(pre<=a[i]+mid)
{
if(pre<a[i]) //因为不降且操作数最小 pre>=a[i]时,把a[i]变成pre,则对于a[i+1],pre不变,pre<a[i]时,pre更新为a[i]
pre=a[i];
continue;
}
else //由于得到的范围最大为a[i]+mid,如果前面的数大于a[i]+mid,那么就不能通过mid次达到目的,标志置0
{
flag=0;
break;
}
}
else
{
if(pre<a[i]&&pre>a[i]+mid-M) //道理同上
pre=a[i];
}
}
if(flag)
{
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
}
void Output()
{
cout<<ans<<endl;
}
int main()
{
Input();
Binary();
Output();
return 0;
}
参考会飞的鱼的博客