P1712 [NOI2016] 区间(线段树&尺取)

考虑对区间长度排序,然后尺取做,显然当左端点右移时,要满足答案,右端点不可能左移。所以尺取是可行的,接下来是怎么统计一个点出现的次数,显然就是区间修改,单点查询。这不线段树裸题嘛,没了。

code

// Problem: P1712 [NOI2016] 区间
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1712
// Memory Limit: 250 MB
// Time Limit: 1000 ms
// Date: 2021-07-14 18:39:44
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=5e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int n,m;
#define lx x<<1
#define rx x<<1|1
struct node{
	int l,r,mx,lz;
}a[N<<3];
void re(int x){
	a[x].mx=max(a[lx].mx,a[rx].mx);
}
void bud(int x,int l,int r){
	a[x].l=l,a[x].r=r,a[x].mx=0;
	if(l==r) return;
	int m=l+r>>1;
	bud(lx,l,m),bud(rx,m+1,r);
}
void pushdown(int x){
	if(a[x].lz){
		a[lx].mx+=a[x].lz,a[rx].mx+=a[x].lz;
		a[lx].lz+=a[x].lz,a[rx].lz+=a[x].lz;
		a[x].lz=0;
	}
}
void upd(int x,int l,int r,int v){
	if(a[x].l>=l&&a[x].r<=r){
		a[x].mx+=v;
		a[x].lz+=v;return;
	}
	pushdown(x);
	int m=a[x].l+a[x].r>>1;
	if(l<=m) upd(lx,l,r,v);
	if(r>m) upd(rx,l,r,v);
	re(x);
}
struct interval{
	int x,y,c;
}b[N];
int c[N<<1],cnt;
bool cmp(interval &a,interval &b){
	return a.c<b.c;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){ 
	scanf("%d%d",&b[i].x,&b[i].y),c[++cnt]=b[i].x;
	c[++cnt]=b[i].y;
	b[i].c=b[i].y-b[i].x;
	}
	sort(c+1,c+cnt+1);
	cnt=unique(c+1,c+cnt+1)-c-1;
	for(int i=1;i<=n;i++){ 
	b[i].x=lower_bound(c+1,c+cnt+1,b[i].x)-c;
	b[i].y=lower_bound(c+1,c+cnt+1,b[i].y)-c;
	}
	bud(1,1,cnt);
	int ans=inf;
	int p=1;
	sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++){
		upd(1,b[i].x,b[i].y,1);
		while(a[1].mx==m){
			upd(1,b[p].x,b[p].y,-1);
			ans=min(ans,b[i].c-b[p++].c);
		}
	}
	ans=ans==inf?-1:ans;
	printf("%d\n",ans);
	return 0;
}