CSUST 看直播 题解(二分+dp)

题目链接

题目思路

所有节点按照\(r\)排序,设\(dp[i]\)表示以\(i\)结尾的最长时间,然后每次转移,就是前\(i-1\)个的\(r\)值小于\(e[i].l\)的转移过来

由于\(r\)是单调上升的,利用二分+前缀最小值dp转移即可,发现这种线段题目基本都是这种思路

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define fi first
#define se second
#define debug printf("aaaaaaaaaaa\n");
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-7;
int n;
int dp[maxn];
int prema[maxn];
struct node{
    int l,r;
}e[maxn];
bool cmp(node a,node b){
    return a.r<b.r;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>e[i].l>>e[i].r;
    }
    sort(e+1,e+1+n,cmp);

    for(int i=1;i<=n;i++){
        int l=1,r=i,ans=0;
        while(l<=r){
            int mid=(l+r)/2;
            if(e[mid].r<e[i].l){
                ans=mid;
                l=mid+1;
            }else{
                r=mid-1;
            }
        }
        dp[i]=prema[ans]+e[i].r-e[i].l+1;
        prema[i]=max(prema[i-1],dp[i]);
    }
    printf("%d\n",prema[n]);
    return 0;
}

上一篇:练习SQL代码


下一篇:FFT