洛谷 T150188 區間(貪心,dp)
阿新 • • 發佈:2020-10-15
傳送門
解題思路
首先可以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 }