求有公共点的m个区间的最长区间的长度与最短区间长度的最小值。
先将区间以长度为关键字从小到大进行排序,易得最小值应该是排序后尽可能相近的两个区间。用头尾两个指针控制,每次更新利用线段树进行区间覆盖来判断是否符合有公共点的条件。
//bzoj4653[Noi2016]区间
#include
#include
#include
#include
#include
#define ll long long
#define lson l,mid,pos<<1
#define rson mid+1,r,pos<<1|1
#define N 500100
#define inf 0x7fffffffffffffff
using namespace std;
struct Tree{int lazy,mx,d;}tree[N<<4];
struct node{ll x,y,len;}a[N];
int n,m,ToT;ll b[N<<1],ans=inf;
bool cmp(node p,node q){return p.len<q.len;}
int find(int x,int l,int r)
{
if (l==r) return l;
int mid=(l+r)>>1;
if (x<=b[mid]) return find(x,l,mid);
else return find(x,mid+1,r);
}
void pushup(int x){tree[x].mx=max(tree[x<<1].mx,tree[x<<1|1].mx);}
void pushdown(int x)
{
int cur=tree[x].lazy;
tree[x<<1].mx+=cur;tree[x<<1].lazy+=cur;
tree[x<<1|1].mx+=cur;tree[x<<1|1].lazy+=cur;
tree[x].lazy=0;
}
void build(int l,int r,int pos)
{
if (l==r) {tree[pos].mx=0;return;}
int mid=(l+r)>>1;
build(lson);build(rson);
pushup(pos);
}
void update(int L,int R,int x,int l,int r,int pos)
{
if (L<=l&&r<=R) {tree[pos].mx+=x;tree[pos].lazy+=x;return;}
int mid=(l+r)>>1;
pushdown(pos);
if (L<=mid) update(L,R,x,lson);
if (R>mid) update(L,R,x,rson);
pushup(pos);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].x,&a[i].y);
b[++ToT]=a[i].x;b[++ToT]=a[i].y;
a[i].len=a[i].y-a[i].x+1;
}
sort(a+1,a+n+1,cmp);sort(b+1,b+ToT+1);
for (int i=1;i<=n;i++) a[i].x=find(a[i].x,1,ToT),a[i].y=find(a[i].y,1,ToT);
//for (int i=1;i<=ToT;i++) printf("%d ",b[i]);printf("\n");
//for (int i=1;i<=n;i++) printf("%d %d %d\n",a[i].x,a[i].y,a[i].len);
build(1,ToT,1);
for (int i=1,j=0;i<=n;i++)
{
while(tree[1].mx<m)
{
if (j==n) break;
j++;
update(a[j].x,a[j].y,1,1,ToT,1);
}
if (tree[1].mx>=m) ans=min(ans,a[j].len-a[i].len);
else break;
update(a[i].x,a[i].y,-1,1,ToT,1);
}
if (ans==inf) printf("-1\n");
else printf("%lld\n",ans);
return 0;
}