bzoj 4653: [Noi2016]区间

Posted lwq12138

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4653: [Noi2016]区间相关的知识,希望对你有一定的参考价值。

4653: [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
题解:
还是要考虑排序。
我们按长度排序,发现最后选出的线段在一段区间上,把区间上的线段一条一条加到线段树中,最大值肯定>=m
然后枚举左端点,发现最近的右端点不断递增,用指针就好了。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=500005;
#define p1 (p<<1)
#define p2 (p<<1|1)
struct node
{
	int a,id;
}p[N<<1];
struct Node
{
	int l,r,len;
}q[N];
int n,m,i,k,ans,x,t[N<<3],add[N<<3],h[N<<1];
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
bool cmp(const node&x,const node&y)
{
	return x.a<y.a;
}
bool Cmp(const Node&x,const Node&y)
{
	return x.len<y.len;
}
void update(int l,int r,int x,int y,int z,int p)
{
	if(x<=l&&r<=y)
	{
		add[p]+=z;
		return;
	}
	if(add[p]!=0)
	{
		add[p1]+=add[p];
		add[p2]+=add[p];
		add[p]=0;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(l,mid,x,y,z,p1);
	if(y>mid) update(mid+1,r,x,y,z,p2);
	t[p]=max(t[p1]+add[p1],t[p2]+add[p2]);
}
int main()
{
	read(n),read(m);
	for(i=1;i<=n*2;i++) p[i].id=i;
	for(i=1;i<=n;i++)
		read(p[i*2-1].a),read(p[i*2].a),q[i].len=p[i*2].a-p[i*2-1].a;
	sort(p+1,p+n*2+1,cmp);
	h[p[1].id]=1;k=1;
	for(i=2;i<=n*2;i++)
	{
		if(p[i].a!=p[i-1].a) k++;
		h[p[i].id]=k;
	}
	for(i=1;i<=n;i++) q[i].l=h[i*2-1],q[i].r=h[i*2];
	sort(q+1,q+n+1,Cmp);
	ans=2e9;
	for(i=1;i<=n;i++)
	{
		while(x<n&&t[1]<m)
		{
			x++;
			update(1,k,q[x].l,q[x].r,1,1);
		}
		if(t[1]>=m) ans=min(ans,q[x].len-q[i].len);
		update(1,k,q[i].l,q[i].r,-1,1);
	}
	if(ans==2e9) cout<<"-1";else cout<<ans;
	return 0;
}

  

 

以上是关于bzoj 4653: [Noi2016]区间的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4653][Noi2016]区间

bzoj 4653: [Noi2016]区间

BZOJ4653: [Noi2016]区间

bzoj4653 [Noi2016]区间

BZOJ4653[Noi2016]区间 双指针法+线段树

[BZOJ]4653: [Noi2016]区间