您的位置:首页 > 其它

NOI 2016 区间

2016-09-11 20:59 232 查看
题目描述:

在数轴上有 n

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

对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

输入格式

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

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

输出格式

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

【题目分析】

线段树+离散化

【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int l,r;
int maxx,tag;
}t[8000001];
int len[1000001],ls[2000001],rank[1000001],l[1000001],r[1000001],n,m;
inline bool cmp (int a,int b)
{return len[a]<len[b];}
inline void push(int k)
{
if (!t[k].tag) return ;
t[k*2].tag+=t[k].tag;  t[k*2].maxx+=t[k].tag;
t[k*2+1].tag+=t[k].tag;t[k*2+1].maxx+=t[k].tag;
t[k].tag=0;
}
inline void add (int k,int l,int r,int opt)
{
push(k);
if (t[k].l>=l&&t[k].r<=r) {t[k].tag+=opt;t[k].maxx+=opt;return;}
int mid=(t[k].l+t[k].r)/2;
if (l<=mid) add(k*2,l,r,opt);
if (r>mid) add(k*2+1,l,r,opt);
t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
}
inline void build (int k,int L,int R)
{
t[k].l=L;t[k].r=R;
if (L==R) return ;
int mid=(L+R)/2;
build(k*2,L,mid);build(k*2+1,mid+1,R);
}
int main()
{
int n,m,top=0;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d%d",&l[i],&r[i]),ls[++top]=l[i],ls[++top]=r[i],len[i]=r[i]-l[i];
sort(ls+1,ls+top+1);
top=unique(ls+1,ls+top+1)-ls-1;

for (int i=1;i<=n;++i)
{
//      int a1=l[i],a2=r[i];
l[i]=lower_bound(ls+1,ls+top+1,l[i])-ls;
r[i]=lower_bound(ls+1,ls+top+1,r[i])-ls;
//      ys[l[i]]=a1;
//      ys[r[i]]=a2;
}
for (int i=1;i<=n;++i) rank[i]=i;
build(1,1,top);
sort(rank+1,rank+n+1,cmp);
int p=1,ans=0x3f3f3f3f;
for (int i=1;i<=n;++i)
{
while (t[1].maxx>=m)
{
//          cout<<p<<"--"<<i<<" "<<len[rank[i-1]]-len[rank[p]]<<endl;
ans=min(ans,len[rank[i-1]]-len[rank[p]]);
add(1,l[rank[p]],r[rank[p]],-1);
p++;
}
//      cout<<t[1].maxx<<endl;
//      cout<<"add"<<l[rank[i]]<<" "<<r[rank[i]]<<endl;
add(1,l[rank[i]],r[rank[i]],1);
}

while (t[1].maxx>=m)
{
//      cout<<p<<"--"<<i<<" "<<len[rank[i-1]]-len[rank[p]]<<endl;
ans=min(ans,len[rank
]-len[rank[p]]);
add(1,l[rank[p]],r[rank[p]],-1);
p++;
}
if (ans!=0x3f3f3f3f)
cout<<ans<<endl;
else cout<<"-1"<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: