• bzoj 4653: [Noi2016]区间


    Description
    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1.

    解题报告:
    难得一道做得出的NOI,首先发现那一个相交的点一定可以是区间的某个端点,所以可以离散左右端点,那么问题就简单了,然后仔细推敲,发现可以按区间长度排序,然后不就是尺取法了么?如果有一个点被覆盖的次数>=m我们就移动左指针,不然我们就一直往后走,对于覆盖次数>=m我们就维护线段树区间最大值,然后区间修改维护指针移动即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define ls (node<<1)
    #define rs (node<<1|1)
    using namespace std;
    const int N=500005;
    int b[N<<1],num=0,n,m,tr[N<<4],mark[N<<4];
    struct node{
    	int l,r,val;
    	bool operator <(const node &pr)const{return val<pr.val;}
    }a[N];
    void upd(int node){tr[node]=Max(tr[ls],tr[rs]);}
    void pushdown(int node){
    	if(!mark[node])return ;
    	int k=mark[node];tr[ls]+=k;tr[rs]+=k;
    	mark[ls]+=k;mark[rs]+=k;mark[node]=0;
    }
    void updata(int l,int r,int node,int sa,int se,int ad){
    	if(l>se || r<sa)return ;
    	if(sa<=l && r<=se){tr[node]+=ad;mark[node]+=ad;return ;}
    	int mid=(l+r)>>1;pushdown(node);
    	updata(l,mid,ls,sa,se,ad);updata(mid+1,r,rs,sa,se,ad);
    	upd(node);
    }
    void work()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%d%d",&a[i].l,&a[i].r),a[i].val=a[i].r-a[i].l;
    		b[++num]=a[i].l;b[++num]=a[i].r;
    	}
    	sort(a+1,a+n+1);sort(b+1,b+num+1);
    	int tot=unique(b+1,b+num+1)-b-1;
    	for(int i=1;i<=n;i++){
    		a[i].l=lower_bound(b+1,b+tot+1,a[i].l)-b;
    		a[i].r=lower_bound(b+1,b+tot+1,a[i].r)-b;
    	}
    	int l=1,ans=2e9;
    	for(int i=1;i<=n;i++){
    		updata(1,tot,1,a[i].l,a[i].r,1);
    		while(tr[1]>=m && l<i){
    			ans=Min(ans,a[i].val-a[l].val);
    			updata(1,tot,1,a[l].l,a[l].r,-1);
    			l++;
    		}
    		if(tr[1]>=m)ans=Min(ans,a[i].val-a[l].val);
    	}
    	if(ans!=2e9)printf("%d
    ",ans);
    	else puts("-1");
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    尝试用博客园写个人日记
    db4o能代替Hibernate吗?
    RSS是否能支持携带扩展的权重信息呢?
    log4view可以更清楚地看log文件,不知道咋用
    tafiti.com体验微软的silverlight
    推荐两个插件DPack, Resharper
    用美味书签的标签实现类似nextlib的知识管理
    进程通讯的多种方式
    多维角度聊聊结对编程
    在Windows下编译和.NET运行MemCached
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7570777.html
Copyright © 2020-2023  润新知