Problem - C - Codeforces
Toad Zitz有一个整数数组,每个整数都在0到m-1的范围内。这些整数是a1,a2...an。
在一次操作中,,iz可以选择一个整数k和k个萦引1..k,使得1si i2. ..fiksn。然后他应该将每个选定的整数a刘j 更改为(aj+ 1lmodm)。整数m对于所有操作和索引都是固定的。
这里xmody表示x除以y的余数。
zitz希望用最少的操作使其数组非降序列。找到这个最小操作数量。
输入:
第一行包含两个整数n和m ( 1sn,m≤300000)——数组中的整数数量和参数m。下一行包含n个空格分隔的整数a1,a2.....an (Osai<m)——给定的数组。
输出:
输出一个整数:Zit-需要进行上述操作的最小次数,使其数组成为非降序列。如果不需要任何操作,则输出О。很容易看出,通过足够的操作,Ztz总是可以使其数组成为非降序列。
Examples
input
Copy
5 3 0 0 0 1 2
output
Copy
0
input
Copy
5 7 0 6 1 3 2
output
Copy
1
注
在第一个例子中,数组已经是不递减的,所以答案是0。
在第二个例子中,您可以选择k=2,i=2,i=5,aray变成[0,1,3,3,ltis不减,所以答案是1。
题解:
贪心的想,如果想让操作数尽可能小,那么最大值是不是也要,尽可能小,我们check操作数,
check时,
1.如果ai > pre
如果ai + x >= m并且(ai + x)%m >=pre
说明,当前ai不用为最大,因为它可以,加上变成跟小的pre
否则pre = a[i]
2.如果ai < pre
如果ai + x < pre
说明我们最优的最小值,ai都无法达到,return 0
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
//#define int long long
int a[1000050];
int n,m;
int b[1000040];
int check(int x)
{
int pre = 0;
for(int i = 1;i <= n;i++)
{
if(a[i] > pre)
{
if(a[i] + x >= m&&(a[i] + x)%m >= pre)
{
}
else
{
pre = a[i];
}
}
else
{
if(a[i] + x >= pre)
{
}
else
{
return 0;
}
}
}
return 1;
}
void solve()
{
cin >> n >> m;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
}
int l = 0,r = m;
while(l <= r)
{
int mid = (l + r)/2;
if(check(mid))
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
cout <<l;
}
//4 2 4
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}