洛谷 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 }