洛谷 T150188 区间(贪心,dp)

 传送门


 解题思路

首先可以dp做,把数据离散化后dp[i]表示到i位置的最多区间数。

把所有区间按照右端点排序从左往右排序,求dp[i]就用右端点为i的区间更新答案。

状态转移可以看代码。

这种做法常数较大,我们还可以用贪心解此题。

我们依旧按照右端点排序,从左往右枚举所有区间,如果当前区间与前面没有重叠(即此区间的左端点在前面选择的区间右端点的右面),就选上这个区间。

感性证明:

能选一定要选,答案+1;

若与前面的有重叠,那么选上这个一定使>=1个区间不能选,而且这个区间的右端点靠右,对后面的区间不利,所以不选。

AC代码

(贪心代码太简单这里只放dp)(其实是懒)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxn=1000005;
 8 int n,d[2*maxn],len,dp[2*maxn],cnt;
 9 struct node{
10     int l,r;
11 }q[maxn];
12 bool cmp(node a,node b){
13     return a.r!=b.r?a.r<b.r:a.l<b.l;
14 }
15 int main(){
16     scanf("%d",&n);
17     for(int i=1;i<=n;i++){
18         scanf("%d%d",&q[i].l,&q[i].r);
19         d[i]=q[i].l;
20         d[i+n]=q[i].r;
21     }
22     sort(d+1,d+2*n+1);
23     sort(q+1,q+n+1,cmp);
24     len=unique(d+1,d+2*n+1)-d-1;
25     for(int i=1;i<=n;i++){
26         q[i].l=lower_bound(d+1,d+len+1,q[i].l)-d;
27         q[i].r=lower_bound(d+1,d+len+1,q[i].r)-d;
28     }
29     for(int i=1;i<=n;i++){
30         while(cnt<q[i].r){
31             cnt++;
32             dp[cnt]=dp[cnt-1];
33         }
34         dp[cnt]=max(dp[cnt],dp[q[i].l]+1);
35     }
36     printf("%d",dp[q[n].r]);
37     return 0;
38 }

 

posted @ 2020-10-14 23:38  尹昱钦  阅读(179)  评论(0编辑  收藏  举报