1. 程式人生 > 實用技巧 >洛谷 T150188 區間(貪心,dp)

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