题解:P12398 「FAOI-R9」决战黎明
P12398 「FAOI-R9」决战黎明 题解
分析
我们可以将其弱化,先考虑只有一条战线的时候。对此,我们有两个比较显然的规律:
- 当我们有两个棋子时,用一个等级为两者之和的棋子会更好。
- 当我们定然无法击败某一个棋子时,我们用很多个等级为 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;
}

浙公网安备 33010602011771号