题解:P12398 「FAOI-R9」决战黎明

P12398 「FAOI-R9」决战黎明 题解

分析

我们可以将其弱化,先考虑只有一条战线的时候。对此,我们有两个比较显然的规律:

  1. 当我们有两个棋子时,用一个等级为两者之和的棋子会更好。
  2. 当我们定然无法击败某一个棋子时,我们用很多个等级为 1 的棋子去消耗它是最好的。

基于这两条,我们可以总结出一个大致的流程:先用一个等级很高的棋子一路过关斩将,然后剩下的所有等级拆成一个个等级为 1 的棋子。

为了实现这个,我们可以记录 \(b_i\) 表示对于某个棋子,我们要用一个等级为多少的棋子从头开始,一路打到这里。然后一直遍历,直到这个值比 \(m\) 更大。然后取前面所有 \(b_i\) 中的最大值,剩下的全部变成 1。

然后我们考虑两条战线时,我们应该怎么做。

这其实就是一个资源分配的问题,我们可以给某一条战线分配足够他打到某个点的等级,剩下的等级分配给另一条战线。枚举一条战线上的点,然后二分出另一条战线可以打到哪里即可。

需要注意的是,可能还会剩余一定分数,我们要将这部分考虑进去。

代码

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

#define int long long

const int N = 2e5 + 5;

int T, n;

int m;

int l[3];

int a[3][N];

int sum[3][N];

int c[3][N];

void solve() {
    cin >> m;
    for(int i = 1;i <= n;i ++ ) {
        cin >> l[i];
        for(int j = 1;j <= l[i];j ++ ) {
            cin >> a[i][j];
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= l[i]; j++) {
            if(a[i][j - 1] + j - 2 == c[i][j - 1]) c[i][j] = max(c[i][j - 1] + 1, a[i][j] + j - 1);
            else c[i][j] = max(c[i][j - 1], a[i][j] + j - 1);
            sum[i][j] = sum[i][j - 1] + a[i][j];
        }
    }
    for(int i = 1;i <= n;i ++ ) {
        for(int j = 1;j < l[i];j ++ ) {
            if(c[i][j] > a[i][j] + j - 1) sum[i][j] ++ ;
        }
    }

    int Sum[3];

    Sum[1] = sum[1][l[1]];
    Sum[2] = sum[2][l[2]];

    // cout << T << ": " << Sum[1] << "\n";
    // cout << 114;
    int ans = 0;
    for(int j = 0;j <= l[1];j ++ ) {
        if(c[1][j] > m) break;
        int L = 1, R = l[2], f = 0;
        while(L <= R) {
            int mid = L + R >> 1;
            if(c[2][mid] <= m - c[1][j]) L = mid + 1, f = mid;
            else R = mid - 1;
        }
        ans = max(ans, sum[1][j] + sum[2][f] + (m - c[1][j] - c[2][f]));
    }
    cout << max(Sum[1] + Sum[2] - ans, 0ll) << "\n";
}

signed main() {
    // int T, n;
    cin >> T >> n;
    while(T -- ) {
        solve();
    }
    return 0;
}
posted @ 2025-09-16 19:44  yanbinmu  阅读(4)  评论(0)    收藏  举报