洛谷 P14520 【MX-S11-T1】战争游戏 题解
洛谷 P14520 【MX-S11-T1】战争游戏 题解
题目链接
思路分析
Task 1
Trick 1:若小 L 的士兵总数大于小 K,则小 L 必定获胜。
证明:小 L 先把所有的士兵聚到 1 点,由于其为先手故肯定不会被小 K 的士兵咬住,然后再平推即可。
Trick 2:若小 K 的士兵总数大于等于小 L 并且 \(a_m\le a_{m+1}\),或者小 K 的士兵总数减 \(a_{m+1}\) 大于等于小 L 的士兵总数加 \(a_{m+1}\),则小 K 必胜。
证明:同 Trick 1,先收缩再平推。
Task 2
有了这两个 Trick,考虑一般情况。发现如果 \(m\) 处的士兵攻占了 \(m+1\) 处,那么由于这时小 K 的士兵若后撤则比小 L 的士兵快一步,只需要考虑小 K 收缩后能否平推即可;若进攻,则只需考虑 \(a_m,a_{m+1},a_{m+2}\) 即可。如果 \(m\) 处的士兵无法攻占 \(m+1\) 处,则当小 L 聚集士兵时,小 K 可以直接收缩。故我们只需要考虑 \(a_m,a_{m+1},a_{m+2}\) 即可。
- 若 \(a_m>a_{m+1}\) 且 \(a_m+a_{m+1}>a_{m+2}\),则 \(m\) 处士兵攻占 \(m+1\) 处,\(m+2\) 处士兵向回撤退;
- 若 \(a_m>a_{m+1}\) 且 \(a_m+a_{m+1}\le a_{m+2}\),则 \(m\) 处士兵向后收缩;
- 若 \(a_m\le a_{m+1}\),则 \(m\) 处士兵向后收缩。
证明:\(m\) 处士兵攻占 \(m+1\) 处后还不会被 \(m+2\) 处的士兵攻占,故进攻可以获得 \(a_{m+1}\) 的士兵;\(m+2\) 处的士兵可能会被 \(m+1\) 处的士兵攻占,若后撤则不会损失,若聚集兵力则 \(m+1\) 处的士兵可以直接撤退或对峙或直接进攻,可能损失兵力,故后撤最优。后面两点证明同理。
Task 3
因此,我们直接按照上面分析的 \(3\) 种情况判断双方士兵总数的变化,然后由于攻占完后双方都会撤退,故比对双方士兵总数即可,可使用前缀和优化。总时间复杂度 \(\mathcal O(n)\)。
代码呈现
十年 OI 一场空,____________
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int t,n;
int a[N];
ll sa[N];
int main(){
scanf("%d",&t);
while (t--){
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",a+i),sa[i]=sa[i-1]+a[i];
for (int i=1;i<n;++i) // 注意 i=n-2 时的边界
putchar((sa[i+(i<n-1 && a[i]>a[i+1] && a[i]+a[i+1]>a[i+2])]<<1)>sa[n]?'1':'0');
putchar('\n');
}
return 0;
}

浙公网安备 33010602011771号