bzoj 4831 [Lydsy1704月赛]序列操作 dp

[Lydsy1704月赛]序列操作

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

2 2
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 }

 

posted @ 2018-04-09 15:06  Kaiser-  阅读(338)  评论(0编辑  收藏  举报