正题
题目链接:https://www.luogu.com.cn/problem/P3507
题目大意
nnn个数,没人轮流取若干个并获得取走的数中最小数的权值,两人的目标都是自己的权值−-−对方的权值最大,求先手的权值−-−后手的权值。
解题思路
肯定是从大往小取,所以我们从小往大dpdpdp。
设fi,0/1f_{i,0/1}fi,0/1表示取了前iii个,最后一步是先/后手。
然后有fi,0=max{fj,1+aj+1}(j<i),fi,1=min{fj,0−aj+1}(j<i)f_{i,0}=max\{f_{j,1}+a_{j+1}\}(j<i),f_{i,1}=min\{f_{j,0}-a_{j+1}\}(j<i)fi,0=max{fj,1+aj+1}(j<i),fi,1=min{fj,0−aj+1}(j<i)
记录一下最大值转移即可,时间复杂度O(n)O(n)O(n)。
可以每次权值取反省去第二维。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e6+10;
ll n,a[N],f[N][2];
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);sort(a+1,a+1+n);for(ll i=1,maxs=0,mins=0;i<=n;i++){mins=min(mins,f[i-1][0]-a[i]);maxs=max(maxs,f[i-1][1]+a[i]);f[i][0]=maxs;f[i][1]=mins;}printf("%lld\n",f[n][0]);
}