bzoj 4831 [Lydsy1704月赛]序列操作 dp
[Lydsy1704月赛]序列操作
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 203 Solved: 69
[Submit][Status][Discuss]
Description
给定一个长度为 n 的非负整数序列 a_1,a_2,...a_n 。你可以使用一种操作:选择在序列中连续的两个正整数,
并使它们分别减一。当你不能继续操作时游戏结束,而你的得分等于你使用的操作次数。你的任务是计算可能的最小
得分和最大得分。
Input
第一行包含一个正整数 T ,表示有 T 组数据,满足 T ≤ 200 。
接下来依次给出每组测试数据。对于每组测试数据:
第一行包含一个正整数 n ,满足 1 ≤ n ≤ 10^5 。
第二行包含 n 个非负整数,表示 a_1,a_2,...a_n ,满足 Σa_i ≤ 10^6 。
约 5 组数据满足 n ≥ 10^3 或 Σa_i ≥ 10^4 。
Output
对于每组测试数据
输出一行两个非负整数,用一个空格隔开,前者表示可能的最小得分,后者表示可能的最大得分。
Sample Input
2
4
1 2 1 3
5
1 2 1 1 3
4
1 2 1 3
5
1 2 1 1 3
Sample Output
2 2
2 3
2 3
HINT
1 #include<queue> 2 #include<vector> 3 #include<cstdio> 4 #include<string> 5 #include<cstring> 6 #include<cstdlib> 7 #include<algorithm> 8 using namespace std; 9 int f[2][1000011],F[2][1000011]; 10 int g[2][1000011],G[2][1000011]; 11 int a[1000011]; 12 int main() 13 { 14 int T; 15 scanf("%d",&T); 16 while(T>0) 17 { 18 T--; 19 int n; 20 scanf("%d",&n); 21 int i,j; 22 int lim=0; 23 for(i=1;i<=n;i++) 24 { 25 scanf("%d",&a[i]); 26 lim=max(lim,a[i]); 27 } 28 if(n==1) 29 { 30 printf("0 0\n"); 31 continue; 32 } 33 for(j=0;j<=lim;j++) 34 { 35 f[0][j]=-1000000000; 36 F[0][j]=-1000000000; 37 g[0][j]=1000000000; 38 G[0][j]=1000000000; 39 f[1][j]=-1000000000; 40 F[1][j]=-1000000000; 41 g[1][j]=1000000000; 42 G[1][j]=1000000000; 43 } 44 int p=0,q=1; 45 int tmp=min(a[1],a[2]); 46 for(i=0;i<tmp;i++) 47 F[p][a[2]-i]=G[p][a[2]-i]=i; 48 f[p][a[2]-tmp]=tmp; 49 g[p][a[2]-tmp]=tmp; 50 51 for(i=3;i<=n;i++) 52 { 53 for(j=1;j<=a[i];j++) 54 { 55 f[q][j]=max(f[p][a[i]-j],F[p][a[i]-j])+a[i]-j; 56 g[q][j]=min(g[p][a[i]-j],G[p][a[i]-j])+a[i]-j; 57 } 58 for(j=a[i];j<=a[i-1];j++) 59 { 60 f[q][0]=max(f[q][0],f[p][j]+a[i]); 61 g[q][0]=min(g[q][0],g[p][j]+a[i]); 62 } 63 f[q][0]=max(f[q][0],F[p][a[i]]+a[i]); 64 g[q][0]=min(g[q][0],G[p][a[i]]+a[i]); 65 for(j=a[i-1]-1;j>=0;j--) 66 { 67 f[p][j]=max(f[p][j],f[p][j+1]); 68 g[p][j]=min(g[p][j],g[p][j+1]); 69 } 70 for(j=1;j<=a[i];j++) 71 { 72 F[q][j]=max(f[p][a[i]-j],F[p][a[i]-j])+a[i]-j; 73 G[q][j]=min(g[p][a[i]-j],G[p][a[i]-j])+a[i]-j; 74 } 75 for(j=0;j<=a[i-1];j++) 76 { 77 f[p][j]=-1000000000; 78 F[p][j]=-1000000000; 79 g[p][j]=1000000000; 80 G[p][j]=1000000000; 81 } 82 p=1-p; 83 q=1-q; 84 } 85 int ansmax=-1000000000,ansmin=1000000000; 86 for(i=0;i<=a[n];i++) 87 { 88 ansmax=max(ansmax,f[p][i]); 89 ansmin=min(ansmin,g[p][i]); 90 } 91 printf("%d %d\n",ansmin,ansmax); 92 } 93 }