跳转至

OJ 1-6 题解

非暴力不合作(超级弱化版)

注意到如果对于每次吃,晚吃是不如早吃的。因为早吃的收益和晚吃一样,但是早吃可以更早的获得收益,在任何情况下都比晚吃好,证明留给读者。

所以如果我们选择吃 \(u\) 次,那必然是前 \(u\) 天选择吃。于是我们枚举这个 \(u\)

记前 \(u\) 天的食物和为 \(S_u\)\(u\) 能使得抗议活动成功当且仅当:

\[ S_u \geq nk + D - s_0 \wedge \forall i \in [u], S_i \geq ik + D - s_0 \]

后一个条件和 \(u\) 无关,如果它不成立则题目无解。

标程列下(\(\text{pac}\)):

#include <bits/stdc++.h>
using namespace std;

const int MN = 1e5 + 5;
int a[MN], n, d, k;
long long s0;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> s0 >> k >> d >> n;
    int N = n;
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    while (s0 - 1ll * k * n < d) {
        ++ans;
        --n;
        if (ans > N)
            break;
        s0 -= k;
        s0 += a[ans];
        if (s0 < d) {
            ans = N + 1;
            break;
        }
    }
    ans = N - ans;
    cout << ans << "\n";
    return 0;
}

内卷(弱化版)

考虑维护 \(a_i \leq a_{i+1}, i \in [n-1]\)\(i\) 的数量 \(k\)

形式化地,写作:

\[ k = \sum_{i \in [n-1]} f(i) = \sum_{i \in [n-1]} \mathbb{I}(a_i \leq a_{i+1}) \]

容易知道,数组不降当且仅当 \(k = n - 1\)

对于操作开始前的 \(k\),可以边输入序列边算好。

此后进行每次修改 \(d\) 位置的操作,我们发现只有 \(f(d)\)\(f(d+1)\) 可能发生变化,那我们此时维护 \(k\) 即可。形式化地,写作:

\[ k \gets k' - f'(d) - f'(d+1) + f(d) + f(d+1) \]

标程列下(\(\text{Bardisk}\)):

#include <cstdio>
int a[200005], b[200005];
int cnt = 0;
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if (i > 1 && a[i] < a[i - 1])
            cnt++;
    }
    for (int i = 1; i <= m; i++) {
        int b, s;
        scanf("%d %d", &b, &s);
        if (b > 1 && a[b] < a[b - 1])
            cnt--;
        if (b < n && a[b] > a[b + 1])
            cnt--;
        a[b] = s;
        if (b > 1 && a[b] < a[b - 1])
            cnt++;
        if (b < n && a[b] > a[b + 1])
            cnt++;
        puts(cnt == 0 ? "YES" : "NO");
    }
}

追忆逝水年华

模拟题,做法如题意。

标程列下(\(\text{pac}\)):

#include <bits/stdc++.h>
using namespace std;

long long a[1005][1005], b[10][10];
bool c[10][10];

int main() {
    int n, m;
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    int nn = n / 8, mm = m / 9;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            cin >> a[i][j];
            b[(i - 1) / nn + 1][(j - 1) / mm + 1] += a[i][j];
        }
    for (int i = 1; i <= 8; ++i)
        for (int j = 1; j <= 9; ++j) b[i][j] /= (nn * mm);
    for (int i = 1; i <= 8; ++i)
        for (int j = 1; j <= 8; ++j) c[i][j] = b[i][j + 1] > b[i][j];
    for (int i = 1; i <= 8; ++i) {
        for (int j = 1; j <= 8; j += 4) {
            int num = (c[i][j] << 3) + (c[i][j + 1] << 2) + (c[i][j + 2] << 1) + (c[i][j + 3]);
            if (num < 10)
                cout << num;
            else
                cout << (char)('A' + num - 10);
        }
    }
    return 0;
}