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为该区间的左右端点。
输出格式
只有一行,包含一个正整数,即最小花费。
【题目分析】
线段树+离散化
【代码】
在数轴上有 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; }
相关文章推荐
- BZOJ 4653: [Noi2016]区间
- 【uoj222】 NOI2016—区间
- Bzoj4653: [Noi2016]区间
- bzoj 4653: [Noi2016]区间
- NOI 2016 区间 解题报告
- 数据结构(线段树):NOI 2016 区间
- BZOJ4653 [NOI2016] 区间 【线段树】
- bzoj 4653: [Noi2016]区间
- bzoj 4653: [Noi2016]区间 (线段树)
- 4653: [Noi2016]区间
- AC日记——NOI2016区间 bzoj 4653
- 【uoj222】 NOI2016—区间
- bzoj 4653: [Noi2016]区间
- BZOJ4653 & 洛谷1712 & UOJ222:[NOI2016]区间——题解
- [BZOJ]4653: [Noi2016]区间
- [NOI 2016]区间
- BZOJ 4653: [Noi2016]区间
- 【noi 2016】区间
- bzoj 4653: [Noi2016]区间 线段树
- BZOJ 4653: [Noi2016]区间