- E. Packmen">CF 847 E. Packmen
- A. Increasing by Modulo">CF 1168 A. Increasing by Modulo
CF 847 E. Packmen
给你一个整数 n(<=1e5) 和一个长为 n 的字符串 s(包含 P. 三种字符,其中 ‘P’ 表示动物,’‘ 表示食物,’.’ 表示空地)。
所有动物每单位时间均能移动一个单位,动物移动到食物上就会吃掉食物,吃掉食物的时间忽略不计。
所有动物可以一起移动。请问吃掉所有食物最少需要多少时间。
思路:
一道较难的二分题
二分+ 双指针
check函数:考虑每个动物向左还是向右(使利益最大化,(吃完前面食物的情况下)向右的步数最多)
static final int N = 100010;
static int n;
static void solve() {
n = ni();
char[] ch = ns().toCharArray();
int l = 1, r = 2 * n;
while (l < r) {
int mid = l + r >> 1;
boolean flag = true;
for (int i = 0, j = 0, pos = -1; i < n; i++) {
if (ch[i] != '*' || pos >= i)
continue;
while (j < n && ch[j] != 'P')
j++;
if (j >= n) {
flag = false;
break;
}
if (j < i) {
pos = j + mid;
j++;
i--;
} else {
if (j - i > mid) {
flag = false;
break;
}
pos = Math.max(i + mid - (j - i), j + (mid - (j - i)) / 2);
j++;
}
}
if (flag)
r = mid;
else
l = mid + 1;
}
out.println(l);
}
CF 1168 A. Increasing by Modulo
输入 n (1≤n≤3e5)、m (1≤m≤3e5) 和一个长为 n 的数组 a,元素值在 [0,m-1] 内。每次操作,你可以选择 a 中的某些数,把每个数 x 改成 (x+1)%m。输出使 a 变成单调非降的最少操作次数。
思路:贪心 + 二分
考虑二分操作数αα,因为每次可以选取任意个数进行操作,所以每个数的操作次数都是 0∼α0∼α 且相互独立。
我们可以记录上一个数的值 LastLast ,显然LastLast越小答案不会更劣,对当前的AiAi而言:
- 如果Ai⩽Last⩽Ai+α,我们可以直接将Ai加到Last即可
- 如果Ai>Last 且 (Ai+α)%m⩾Last,我们也可以将Ai加到Last
- 如果Ai>Last 且 (Ai+α)%m<Last,那我们就不对Ai操作
- 如果Ai<Last 且 Ai+α<Last,那无论怎么操作都不可行
static final int N = 300010;
static int[] a = new int[N];
static int n, m;
static void solve() {
n = ni();
m = ni();
for (int i = 1; i <= n; i++)
a[i] = ni();
int l = 0, r = m;
while (l < r) {
int mid = l + r >> 1;
boolean flag = true;
int pre = 0;
for (int i = 1; i <= n; i++) {
if (a[i] >= pre) {
if (a[i] + mid >= m) {
if ((a[i] + mid) % m < pre) pre = a[i];
} else pre = a[i];
} else if (a[i] + mid < pre) {
flag = false;
break;
}
}
if (flag) r = mid;
else l = mid + 1;
}
out.println(l);
}