POJ 1836 Alignment

有一排人,身高可能不同,现在有一个理想状态是这排的每个人向左或向右看没有被挡住视野(当遇到等高或更高的人时会被挡住),现在问最少让几人出列可以达到这个理想状态。

最少人出列,其实就是一个人数最多的理想状态。求一个人数最多的类似"山峰"的高度排列。那就可以从左到右、从右到左各求一遍LIS

 

开始用 O(n2)的写法WA了,错在搞错dp[i] 的含义,dp[i]代表以i为尾的LIS,最后输出答案时应该枚举 dp[i]+dp[j]

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int height[1024];
 6 int dp1[1024];//up
 7 int dp2[1024];//down
 8 
 9 int main(){
10     int N;
11     scanf("%d",&N);
12     for(int i=0;i<N;++i){
13         double tmp;
14         scanf("%lf",&tmp);
15         height[i]=tmp*100000+0.1;
16     }
17     for(int i=0;i<N;++i){
18         dp1[i]=1;
19         for(int j=0;j<i;++j){
20             if(height[j]<height[i]) dp1[i]=max(dp1[i],dp1[j]+1);
21         }
22     }
23     for(int i=N-1;i>=0;i--){
24         dp2[i]=1;
25         for(int j=N-1;j>i;--j){
26             if(height[j]<height[i]) dp2[i]=max(dp2[i],dp2[j]+1);
27         }
28     }
29     //for(int i=0;i<N;++i) printf("i : %d\tup: %d , down: %d\n",i,dp1[i],dp2[i]);
30     int ans=-1;
31     //ans=max(ans,dp2[0]);
32     //for(int i=0;i<N-1;++i)ans=max(ans,dp1[i]+dp2[i+1]);
33     //ans=max(ans,dp1[N-1]);
34     for(int i=0;i<N;++i)
35         for(int j=i+1;j<N;++j)
36             ans=max(ans,dp1[i]+dp2[j]);
37     printf("%d\n",N-ans);
38 }
View Code

 

用O(nlogn)的写法

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int INF=0x3f3f3f3f;
 6 int height[1024];
 7 int dp1[1024];//up
 8 int dp2[1024];//down
 9 int S[1024];
10 int tot;
11 
12 int B_S(int l,int r,int ob){
13     int mid;
14     r--;
15     while(l<=r){
16         mid=(l+r)>>1;
17         if(S[mid]>ob) r=mid-1;
18         else l=mid+1;
19     }
20     return l;
21 }
22 
23 int main(){
24     int N;
25     scanf("%d",&N);
26     for(int i=0;i<N;++i){
27         double tmp;
28         scanf("%lf",&tmp);
29         height[i]=tmp*100000+0.1;
30     }
31     
32     fill(S,S+N,INF);
33     for(int i=0;i<N;++i){
34         int pos=lower_bound(S,S+N,height[i])-S;
35         dp1[i]=pos+1;
36         S[pos]=height[i];
37     }
38     fill(S,S+N,INF);
39     for(int i=N-1;i>=0;i--){
40         int pos=lower_bound(S,S+N,height[i])-S;
41         dp2[i]=pos+1;
42         S[pos]=height[i];
43     }
44     //for(int i=0;i<N;++i) printf("i : %d\tup: %d , down: %d\n",i,dp1[i],dp2[i]);
45     int ans=-1;
46     //ans=max(ans,dp2[0]);
47     //for(int i=0;i<N-1;++i)ans=max(ans,dp1[i]+dp2[i+1]);
48     //ans=max(ans,dp1[N-1]);
49     for(int i=0;i<N;++i)
50         for(int j=i+1;j<N;++j)
51             ans=max(ans,dp1[i]+dp2[j]);
52     printf("%d\n",N-ans);
53 }
View Code
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int height[1024];
 6 int dp1[1024];//up
 7 int dp2[1024];//down
 8 int S[1024];
 9 int tot;
10 
11 int B_S(int l,int r,int ob){
12     int mid;
13     r--;
14     while(l<=r){
15         mid=(l+r)>>1;
16         if(S[mid]>ob) r=mid-1;
17         else l=mid+1;
18     }
19     return l;
20 }
21 
22 int main(){
23     int N;
24     scanf("%d",&N);
25     for(int i=0;i<N;++i){
26         double tmp;
27         scanf("%lf",&tmp);
28         height[i]=tmp*100000+0.1;
29     }
30     tot=0;
31     for(int i=0;i<N;++i){
32         if(tot==0||S[tot-1]<height[i]) S[tot++]=height[i];
33         else{
34             //int pos=B_S(0,tot,height[i]);
35             int pos=lower_bound(S,S+tot,height[i])-S;
36             S[pos]=height[i];
37         }
38         dp1[i]=tot;
39     }
40     tot=0;
41     for(int i=N-1;i>=0;i--){
42         if(tot==0||S[tot-1]<height[i]) S[tot++]=height[i];
43         else{
44             //int pos=B_S(0,tot,height[i]);
45             int pos=lower_bound(S,S+tot,height[i])-S;
46             S[pos]=height[i];
47         }
48         dp2[i]=tot;
49     }
50     //for(int i=0;i<N;++i) printf("i : %d\tup: %d , down: %d\n",i,dp1[i],dp2[i]);
51     int ans=-1;
52     //ans=max(ans,dp2[0]);
53     //for(int i=0;i<N-1;++i)ans=max(ans,dp1[i]+dp2[i+1]);
54     //ans=max(ans,dp1[N-1]);
55     for(int i=0;i<N;++i)
56         for(int j=i+1;j<N;++j)
57             ans=max(ans,dp1[i]+dp2[j]);
58     printf("%d\n",N-ans);
59 }
View Code

一种单调栈,一种从修改预设数组,都是二分

开始一直在用upper_bound,后来脑补跑数据才发现,upper_bound只能用来找不下降子序列,lower_bound是用来找严格上升子序列。

posted on 2018-09-03 22:54  Emiya_Kiritsugu  阅读(161)  评论(0编辑  收藏  举报

导航