• 并不对劲的bzoj4651:loj2086:uoj222:p1712:[NOI2016]区间


    题目大意

    (n)((nleq 5*10^5))个闭区间([L_1,R_1],[L_2,R_2],...,[L_n,R_n])((forall iin [1,n],0leq L_ileq R_ileq 10^9))
    要选取(m)个区间,使这(m)个区间的交不为空,方案的花费为被选中的区间中 长度最长的区间的长度 减 长度最短的区间的长度
    求花费最小的方案,或判断无解

    题解

    (n)个区间按区间长度排序
    问题转化成对于所有满足存在一点被([L_l,R_l],[L_{l+1},R_{l+1}],...,[L_r,R_r])覆盖不少于(m)次的([l,r])中,使(R_r-L_r-R_l+L_l)最小
    发现将合法的([l,r])中的(r)右移时,要想产生更优的解,(l)也得右移,也就是单调性
    那就可以从小到大枚举(r),维护当前最优解的(l)的位置,用权值线段树或离散化后用线段树判断是否有一点被覆盖超过(m)
    但是(n)比较大,用权值线段树可能会被卡

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define maxn 500010
    #define ls (u<<1)
    #define rs (u<<1|1)
    #define mi (l+r>>1)
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x==0){putchar('0'),putchar('
    ');return;}
        int f=0;char ch[20];
        if(x<0)putchar('-'),x=-x;
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
        return;
    }
    int n,ext[maxn<<1],cnte,tr[maxn<<3],mk[maxn<<3],ans=-1,m;
    struct node{int l,r;}nd[maxn];
    bool cmp(node x,node y){return x.r-x.l<y.r-y.l;}
    void mark(int u,int k){tr[u]+=k,mk[u]+=k;}
    void pd(int u){if(mk[u])mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}
    void pu(int u){tr[u]=max(tr[ls],tr[rs]);}
    void add(int u,int l,int r,int x,int y,int k)
    {
        if(x<=l&&r<=y)return mark(u,k);
        pd(u);
        if(x<=mi)add(ls,l,mi,x,y,k);
        if(y>mi)add(rs,mi+1,r,x,y,k);
        return pu(u);
    }
    int getr(int x)
    {
        int l=1,r=cnte,ans=cnte+1;
        while(l<=r)
        {
            int mid=mi;
            if(ext[mid]<x)l=mid+1;
            else if(ext[mid]>x)r=mid-1;
            else ans=min(ans,mid),r=mid-1;
        }
        return ans;
    }
    int jud(int i,int j)
    {
        add(1,1,cnte,getr(nd[j].l),getr(nd[j].r),-1);
        int x=tr[1];
        if(x>=m)return 1;
        add(1,1,cnte,getr(nd[j].l),getr(nd[j].r),1);return 0;
    }
    signed main()
    {
        n=read(),m=read();
        rep(i,1,n)nd[i].l=read(),nd[i].r=read(),ext[++cnte]=nd[i].l,ext[++cnte]=nd[i].r;
        sort(nd+1,nd+n+1,cmp),sort(ext+1,ext+cnte+1);int j=1;
        rep(i,1,n)
        {
        	add(1,1,cnte,getr(nd[i].l),getr(nd[i].r),1);
        	while(jud(i,j)&&j<=i)j++;
        	if(tr[1]>=m)ans=(ans==-1)?(nd[i].r-nd[i].l-nd[j].r+nd[j].l):min(ans,(nd[i].r-nd[i].l-nd[j].r+nd[j].l));
        }
        write(ans);
        return 0;
    }
    
  • 相关阅读:
    解决FileReader读取文件乱码问题
    comparable 与 comparator
    JavaScript添加水印
    mybatis里oracle与MySQL的insert_update
    关于回车换行
    solr创建collection
    hbase相关配置说明
    java基础(十一)--- IO
    java基础(十)--- 异常
    c++中的vector原理
  • 原文地址:https://www.cnblogs.com/xzyf/p/10391451.html
Copyright © 2020-2023  润新知