[UOJ #222][NOI2016]区间(线段树)
Description
在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值
求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。
Solution
对区间的长度排序,离散化,然后线段树维护每个点被覆盖过的次数,根据决策的单调性就可做了
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define MAXN 500005 #define INF 0x3f3f3f3f using namespace std; int n,m; int a[MAXN*2],cnt=0; int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0';c=getchar(); } return x*f; } struct Node1 { int L,R,len; }d[MAXN]; bool cmp(Node1 x,Node1 y) { return x.len<y.len; } struct Node2 { int l,r,tag,maxn; }t[MAXN*8]; void pushdown(int idx) { if(t[idx].tag&&t[idx].l!=t[idx].r) { int tag=t[idx].tag; t[idx].tag=0; t[idx<<1].tag+=tag; t[idx<<1|1].tag+=tag; t[idx<<1].maxn+=tag; t[idx<<1|1].maxn+=tag; } } void update(int idx) { t[idx].maxn=max(t[idx<<1].maxn,t[idx<<1|1].maxn); } void build(int idx,int l,int r) { t[idx].l=l,t[idx].r=r,t[idx].maxn=t[idx].tag=0; if(l==r)return; int mid=(l+r)>>1; build(idx<<1,l,mid); build(idx<<1|1,mid+1,r); } void add(int idx,int x,int y,int z) { if(x<=t[idx].l&&y>=t[idx].r) { t[idx].maxn+=z; t[idx].tag+=z; return; } pushdown(idx); int mid=(t[idx].l+t[idx].r)>>1; if(y<=mid)add(idx<<1,x,y,z); else if(x>mid)add(idx<<1|1,x,y,z); else add(idx<<1,x,y,z),add(idx<<1|1,x,y,z); update(idx); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { d[i].L=read(),d[i].R=read(); a[++cnt]=d[i].L,a[++cnt]=d[i].R; d[i].len=d[i].R-d[i].L; } sort(a+1,a+1+cnt); cnt=unique(a+1,a+1+cnt)-a-1; sort(d+1,d+1+n,cmp); for(int i=1;i<=n;i++) { d[i].L=lower_bound(a+1,a+1+cnt,d[i].L)-a; d[i].R=lower_bound(a+1,a+1+cnt,d[i].R)-a; } int ans=INF,top=0; build(1,1,cnt); for(int i=1;i<=n;i++) { while(top<n&&t[1].maxn<m) { ++top; add(1,d[top].L,d[top].R,1); } if(t[1].maxn>=m)ans=min(ans,d[top].len-d[i].len); add(1,d[i].L,d[i].R,-1); } if(ans==INF)printf("-1\n"); else printf("%d\n",ans); return 0; }