问题描述
我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有Nleft(1leq Nleq 5*{10}^{4}
ight)N(1≤N≤5∗104)个数,每次KK都会先拿数。每次可以拿任意多个数,直到NN个数被拿完。每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大。在这样的情况下,最终KK的得分减去对手的得分会是多少?
输入描述
第一行一个数Tleft( 1leq Tleq 10
ight)T(1≤T≤10),表示数据组数。
对于每组数据包含两行,第一行一个整数Nleft(1leq Nleq 5*{10}^{4}
ight)N(1≤N≤5∗104),表示个数,第二行NN个正整数(不超过{10}^{9}109)。
输出描述
对于每一个数据输出一个整数,表示最终KK的得分减去对手的得分。
输入样例
1 3 1 3 1
输出样例
2
Hint
首先KK取走3,然后对手取走两个1,那么最终分差为2。
题解:
首先,对数从小到大排序。
用dp[i]表示,当只有前i个数时,先取的人能够得到的分数差的最大值。 dp[0]=0
那么我们容易得到
dp[1] = a[1]-dp[0].
dp[2] = max(a[2]-dp[1],a[1]-dp[0]) = max(a2-dp[1],dp[1]).
dp[3] = max(a[3]-dp[2],a[2]-dp[1],a[1]-dp[0]) = max(dp[2],a[3]-dp[2])
...
dp[i] = max(a[i]-dp[i-1],dp[i-1]).
计算的时间复杂度o(n),排序o(nlogn),总o(nlogn)
注意到 dp[i] 的计算只有到dp[i-1],因此不需要储存所有dp,对内存进行优化
AC代码:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<math.h> 7 #include<algorithm> 8 #include<queue> 9 #include<set> 10 #include<bitset> 11 #include<map> 12 #include<vector> 13 #include<stdlib.h> 14 using namespace std; 15 #define ll long long 16 #define eps 1e-10 17 #define MOD 1000000007 18 #define N 60000 19 #define inf 1e12 20 int n; 21 int a[N]; 22 int main() 23 { 24 int t; 25 scanf("%d",&t); 26 while(t--){ 27 scanf("%d",&n); 28 for(int i=0;i<n;i++){ 29 scanf("%d",&a[i]); 30 } 31 sort(a,a+n); 32 33 int ans=0; 34 for(int i=0;i<n;i++){ 35 ans = max(ans,a[i]-ans); 36 a[i]=ans; 37 } 38 printf("%d ",ans); 39 } 40 return 0; 41 }