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