> 文章列表 > C. Increasing by Modulo(贪心 + 二分)

C. Increasing by Modulo(贪心 + 二分)

C. Increasing by Modulo(贪心 + 二分)

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 4signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);int t = 1;
//	cin >> t;while(t--){solve(); }
}

 

虫部落