[HDOJ5773]The All-purpose Zero(贪心,DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5773

题意:给n个数,其中0可以用任何数字代替,问如何替换0使整个数列中的LIS最长。

0可以用任何数字替换,那显而易见不管如何最长的情况就是0全部用上。这是网上的思路,维护前缀和sum表示0的个数,在所有数字上减掉之前0的个数,求一遍LIS就行了。这个贪心好巧。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 100100;
 5 int n;
 6 int a[maxn], s[maxn], sum[maxn];
 7 int dp[maxn];
 8 bool vis[maxn];
 9 
10 int bs(int ll, int rr, int v) {
11     while(ll <= rr) {
12         int mm = (ll + rr) >> 1;
13         if(s[mm] < v) ll = mm + 1;
14         else rr = mm - 1;
15     }
16     return ll;
17 }
18 
19 int main() {
20     // freopen("in", "r", stdin);
21     int T, _ = 1;
22     scanf("%d", &T);
23     while(T--) {
24         printf("Case #%d: ", _++);
25         memset(dp, 0, sizeof(dp));
26         memset(s, 0x7f, sizeof(s));
27         memset(sum, 0, sizeof(sum));
28         memset(vis, 0, sizeof(vis));
29         scanf("%d", &n);
30         for(int i = 1; i <= n; i++) {
31             scanf("%d", &a[i]);
32         }
33         for(int i = 1; i <= n; i++) {
34             if(a[i] == 0) sum[i] = sum[i-1] + 1;
35             else sum[i] = sum[i-1];
36         }
37         for(int i = 1; i <= n; i++) {
38             if(a[i] == 0) {
39                 vis[i] = 1;
40                 continue;
41             }
42             a[i] -= sum[i];
43         }
44         int ret = 0;
45         for(int i = 1; i <= n; i++) {
46             if(vis[i]) continue;
47             dp[i] = bs(1, i, a[i]);
48             s[dp[i]] = min(s[dp[i]], a[i]);
49             ret = max(ret, dp[i]);
50         }
51         printf("%d\n", ret+sum[n]);
52     }
53     return 0;
54 }

 

posted @ 2016-10-22 11:44  Kirai  阅读(204)  评论(0编辑  收藏  举报