• 最小覆盖_KEY


    最小覆盖(cover)、、线段树

    【题目描述】

    给定 N 个区间[Li,Ri],需要你按照顺序选出一个区间序列使得[1,M]完全被覆盖。并且在选出来的序列中,某个区间[a,b]之前必须保证[1,a]都被已经选中的区间覆盖(即没有“断开”的地方)。求出最少需要选多少区间

    【输入文件】

    第一行两个整数 M 和 N。

    以下 N 行每行两个正整数 Li,Ri 表示这个区间。

    【输出文件】

    一个整数,表示最少的区间数。

    【样例输入】

    40 6

    20 30

    1 10

    10 20

    20 30

    15 25

    30 40

    【样例输出】

    4

    【样例解释】

    [1,10]-[10,20]-[20,30]-[30,40]

    【数据规模】

    对于 100%的数据 1<=N<=500000, 0<=M<=50000

    先不看数据,知道这是一道DP题。

    F[i]表示填满1~i区间最少需要几个区间。

    因为数据范围大,所以用线段树维护。

    code

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define C c = tc ( )
    using namespace std;
    inline char tc(){
        static char fl[1000000],*A,*B;
        return A==B&&(B=(A=fl)+fread(fl,1,1000000,stdin),A==B)?EOF:*A++;
    }
    inline int read(){
        char c;int x=0,y=1;
        while(!isdigit(C)&&c!='-');c=='-'?y=-1:x=c-'0';
        while(isdigit(C))x=x*10+c-'0';
        return x*y;
    }
    struct node{
        int x,y;
    }a[500001];
    int m,n,seg[50000*4+1],add[50000*4+1];
    void up(int node){seg[node]=min(seg[node<<1],seg[(node<<1)+1]);}
    void down(int node){
        if(add[node]!=2147483647){
            add[node*2]=min(add[node*2],add[node]);
            add[node*2+1]=min(add[node*2+1],add[node]);
            seg[node*2]=min(seg[node*2],add[node]);
            seg[node*2+1]=min(seg[node*2+1],add[node]);
            add[node]=2147483647;
        }
        return ;
    }
    int query(int node,int l,int r,int ql,int qr){
        if(ql<=l&&qr>=r)return seg[node];
        int mid=(l+r)>>1;
        down(node);
        int ans=2147483647;
        if(ql<=mid)ans=min(ans,query(node*2,l,mid,ql,qr));
        if(qr>mid) ans=min(ans,query(node*2+1,mid+1,r,ql,qr));
        return ans;
    }
    void change(int node,int l,int r,int cl,int cr,int v){
        if(cl<=l&&cr>=r){
            seg[node]=min(seg[node],v);
            add[node]=min(add[node],v);
            return ;
        }
        int mid=(l+r)>>1;
        down(node);
        if(cl<=mid)change(node*2,l,mid,cl,cr,v);
        if(cr>mid) change(node*2+1,mid+1,r,cl,cr,v);
        up(node);
    }
    int main(){
        freopen("cover.in","r",stdin);
        freopen("cover.out","w",stdout);
        m=read(),n=read();
            for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read();
            for(int i=1;i<=m*4;i++)seg[i]=add[i]=2147483647;
        change(1,1,m,1,1,0);
            for(int i=1;i<=n;i++){
                int p=query(1,1,m,a[i].x,a[i].y);
                if(p==2147483647)continue;
                change(1,1,m,a[i].x,a[i].y,p+1);
            }
        printf("%d",query(1,1,m,m,m));
        fclose(stdin),fclose(stdout);
        return 0;
    }

    膜拜度神

  • 相关阅读:
    Arcgis中修改字段名方法
    题事件名称为CLR20r3
    【转】CLR20R3 程序终止的几种解决方案
    Ajax+asp.net无刷新验证用户名
    [转载]C/C++编译器cl.exe的命令选项
    [网络整理]DEBUG命令使用解析五
    [网络整理]DEBUG命令使用解析一
    [网络整理]DEBUG命令使用解析六
    [易学C#]C#3.0语言新特性
    [易学C#]C#3.0语言新特性之Lambda表达式
  • 原文地址:https://www.cnblogs.com/Cptraser/p/7593442.html
Copyright © 2020-2023  润新知