zoukankan      html  css  js  c++  java
  • [bzoj4653] [NOI2016]区间

    Description

    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。

    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。

    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

    Input

    第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n

    接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。

    N<=500000,M<=200000,0≤li≤ri≤10^9

    Output

    只有一行,包含一个正整数,即最小花费。

    Sample Input

    6 3
    3 5
    1 2
    3 4
    2 2
    1 5
    1 4
    

    Sample Output

    2
    

    Solution

    由于答案是最大的区间减最小的区间,而且和顺序没关系,所以可以按区间长度排序。

    按顺序加入,显然当有一个点的覆盖次数大于(m)时,就不加了。

    然后对于已经加进去的,从小到大删除,直到覆盖次数全都小于(m)时,最后一个删掉的和当前加入的最大的区间肯定可以构成一个当前最优的方案。

    然后开个线段树,拿两个指针指一下,模拟下上面的过程就行了。

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
    	if(x<0) putchar('-'),x=-x;
    	if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 5e6+1;
    
    struct node {
    	int l,r,len;
    	bool operator < (const node &rhs) const {return len<rhs.len;} 
    }in[maxn<<1];
    int a[maxn],b[maxn],n,m,tot,head,tail;
    
    #define ls p<<1
    #define rs p<<1|1
    #define mid ((l+r)>>1)
    
    struct Segment_Tree {
    	int tr[maxn],tag[maxn];
    	void push_tag(int p,int v) {tr[p]+=v,tag[p]+=v;}
    	void update(int p) {tr[p]=max(tr[ls],tr[rs]);}
    	void pushdown(int p) {
    		if(tag[p]) push_tag(ls,tag[p]),push_tag(rs,tag[p]),tag[p]=0;
    	}
    	void modify(int p,int l,int r,int x,int y,int v) {
    		if(x<=l&&r<=y) return push_tag(p,v),void();
    		pushdown(p);
    		if(x<=mid) modify(ls,l,mid,x,y,v);
    		if(y>mid) modify(rs,mid+1,r,x,y,v);
    		update(p);
    	}
    }SGT;
    
    #undef ls
    #undef rs
    #undef mid
    
    int main() {
    	read(n),read(m);
    	for(int i=1;i<=n;i++) read(in[i].l),read(in[i].r),in[i].len=in[i].r-in[i].l;
    	sort(in+1,in+n+1);
    	for(int i=1;i<=n;i++) a[++tot]=in[i].l,a[++tot]=in[i].r;
    	sort(a+1,a+tot+1);int M=unique(a+1,a+tot+1)-a-1;
    	for(int i=1;i<=n;i++) {
    		in[i].l=lower_bound(a+1,a+M+1,in[i].l)-a;
    		in[i].r=lower_bound(a+1,a+M+1,in[i].r)-a;
    	}
    	int ans=1e9;
    	while(tail<n) {
    		while(tail<n&&SGT.tr[1]<m) tail++,SGT.modify(1,1,n*2,in[tail].l,in[tail].r,1);
    		if(SGT.tr[1]<m) break;
    		while(head<=tail&&SGT.tr[1]>=m) head++,SGT.modify(1,1,n*2,in[head].l,in[head].r,-1);
    		ans=min(ans,in[tail].len-in[head].len);
    	}
    	if(ans!=1e9) write(ans);else puts("-1");
    	return 0;
    }
    
  • 相关阅读:
    声明了变量并赋了初始值,但在VS中报当前上下文中不存在名称“ XXX”的错误 Kevin
    delphi中的nil值 Kevin
    MVC3 + Ajax 图片上传总结 Kevin
    EntityFramework 更新数据库的问题 Kevin
    MVC3 EntityFramework 插入Mysql数据库 乱码问题 Kevin
    MVC Html 编码问题 Kevin
    周鸿祎:共享软件无合理商业模式才变流氓
    C++界面库 Xtreme Toolkit Pro[转载]
    《创业10个小诀窍》
    软件商业模式分析之-迅雷
  • 原文地址:https://www.cnblogs.com/hbyer/p/10172874.html
Copyright © 2011-2022 走看看