【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero

题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=5773

题目大意

  T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何自然数)

题目思路:

  【动态规划】【二分】【最长上升子序列】

  按最长上升子序列做,遇到0的时候更新所有长度的最优解。(这种暴力解法都能过?而且还比标解快?)

 1 //
 2 //by coolxxx
 3 //
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<string>
 7 #include<iomanip>
 8 #include<memory.h>
 9 #include<time.h>
10 #include<stdio.h>
11 #include<stdlib.h>
12 #include<string.h>
13 //#include<stdbool.h>
14 #include<math.h>
15 #define min(a,b) ((a)<(b)?(a):(b))
16 #define max(a,b) ((a)>(b)?(a):(b))
17 #define abs(a) ((a)>0?(a):(-(a)))
18 #define lowbit(a) (a&(-a))
19 #define sqr(a) ((a)*(a))
20 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
21 #define eps (1e-8)
22 #define J 10000000
23 #define MAX 0x7f7f7f7f
24 #define PI 3.1415926535897
25 #define N 100004
26 using namespace std;
27 typedef long long LL;
28 int cas,cass;
29 int n,m,lll,ans;
30 int a[N],q[N];
31 void work()
32 {
33     int i,j,l,r,mid;
34     lll=0;
35     memset(q,-1,sizeof(q));
36     for(i=1;i<=n;i++)
37     {
38         if(a[i]==0)
39         {
40             q[lll+1]=q[lll]+1;
41             for(j=lll;j>1;j--)q[j]=min(q[j-1]+1,q[j]);
42             q[1]=0;lll++;
43             continue;
44         }
45         l=0,r=lll;
46         while(l<r)
47         {
48             mid=(l+r+1)>>1;
49             if(a[i]>q[mid])l=mid;
50             else r=mid-1;
51         }
52         q[r+1]=a[i];
53         lll=max(lll,r+1);
54     }
55 }
56 int main()
57 {
58     #ifndef ONLINE_JUDGE
59     freopen("1.txt","r",stdin);
60 //    freopen("2.txt","w",stdout);
61     #endif
62     int i,j;
63 //    for(scanf("%d",&cas);cas;cas--)
64     for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
65 //    while(~scanf("%s",s))
66 //    while(~scanf("%d",&n))
67     {
68         printf("Case #%d: ",cass);
69         scanf("%d",&n);
70         for(i=1;i<=n;i++)
71         {
72             scanf("%d",&a[i]);
73         }
74         work();
75         printf("%d\n",lll);
76     }
77     return 0;
78 }
79 /*
80 //
81 
82 //
83 */
View Code

   正解是把0先都拿出来,非0的数都减去它前面0的个数(0可以变成任何自然数),求最长上升子序列,再把0的数加上即为答案。

 1 //
 2 //by coolxxx
 3 ////<bits/stdc++.h>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<string>
 7 #include<iomanip>
 8 #include<memory.h>
 9 #include<time.h>
10 #include<stdio.h>
11 #include<stdlib.h>
12 #include<string.h>
13 //#include<stdbool.h>
14 #include<math.h>
15 #define min(a,b) ((a)<(b)?(a):(b))
16 #define max(a,b) ((a)>(b)?(a):(b))
17 #define abs(a) ((a)>0?(a):(-(a)))
18 #define lowbit(a) (a&(-a))
19 #define sqr(a) ((a)*(a))
20 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
21 #define mem(a,b) memset(a,b,sizeof(a))
22 #define eps (1e-8)
23 #define J 10000000
24 #define MAX 0x7f7f7f7f
25 #define PI 3.14159265358979323
26 #define N 100004
27 using namespace std;
28 typedef long long LL;
29 int cas,cass;
30 int n,m,lll,ans;
31 int a[N],q[N];
32 void work()
33 {
34     int i,j,l,r,mid;
35     lll=0;
36     memset(q,-1,sizeof(q));
37     for(i=1;i<=n;i++)
38     {
39         l=0,r=lll;
40         while(l<r)
41         {
42             mid=(l+r+1)>>1;
43             if(a[i]>q[mid])l=mid;
44             else r=mid-1;
45         }
46         q[r+1]=a[i];
47         lll=max(lll,r+1);
48     }
49 }
50 int main()
51 {
52     #ifndef ONLINE_JUDGE
53     freopen("1.txt","r",stdin);
54 //    freopen("2.txt","w",stdout);
55     #endif
56     int i,j;
57 //    for(scanf("%d",&cas);cas;cas--)
58     for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
59 //    while(~scanf("%s",s))
60 //    while(~scanf("%d",&n))
61     {
62         printf("Case #%d: ",cass);
63         scanf("%d",&n);
64         m=0;
65         for(i=1;i<=n;i++)
66         {
67             scanf("%d",&a[i]);
68             if(a[i]==0)n--,i--,m++;
69             else a[i]-=m;
70         }
71         work();
72         printf("%d\n",lll+m);
73     }
74     return 0;
75 }
76 /*
77 //
78 
79 //
80 */
View Code

 

  

posted @ 2016-08-14 10:06  Cool639zhu  阅读(330)  评论(0编辑  收藏  举报