【题解】洛谷P1712: [NOI2016] 区间

P1712 [NOI2016] 区间

我对尺取法并不敏感,所以感觉有点难度,我们想到按照区间长度排序加入使得满足单调性,直到有一个区间的覆盖次数达到了m就可以计算了,而这个就是尺取法,单调性使得我们答案总是最优的。

覆盖次数就可以用线段树做,而且数据范围很大需要离散化,计算答案时注意把答案带回到离散数组中。

我们思路进度:想到可能需要覆盖但不会如何使得区间答案最小化,之后我又以为要线段树记录最大值最小值。

最小化最大最小值使用尺取。

#include <bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1 
#define re register 
using namespace std;
const int N=5e5+10;

int n,m;
int b[N<<1];
struct ss{
	int l,r;
}a[N];

int ans=2e9;

int t[N<<3],add[N<<3];

int getsum(int l,int r){
	return (b[a[r].r]-b[a[r].l])-(b[a[l].r]-b[a[l].l]);
}

bool cmp(ss g,ss h){
	return (g.r-g.l)<(h.r-h.l);
}

void read(){
	cin>>n>>m;
	for(re int i=1;i<=n;i++){
		cin>>a[i].l>>a[i].r;
		b[i*2-1]=a[i].l;
		b[i*2]=a[i].r;
	}
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+n*2+1);
	int tot=unique(b+1,b+2*n+1)-b-1;
	for(re int i=1;i<=n;i++){
		a[i].l=lower_bound(b+1,b+1+tot,a[i].l)-b;
		a[i].r=lower_bound(b+1,b+1+tot,a[i].r)-b;
	}
}

void pushdown(int p,int pl,int pr){
	if(add[p]){
		int tag=add[p];
		add[p]=0;
		
		t[ls]+=tag;
		t[rs]+=tag;
		
		add[ls]+=tag;	
		add[rs]+=tag;
	}
}

void change(int p,int pl,int pr,int l,int r,int x){
	if(pl>r||pr<l){
		return;
	}
	if(pl>=l&&pr<=r){
		t[p]+=x;
		add[p]+=x;
		return; 
	}
	pushdown(p,pl,pr);
	int mid=(pl+pr)>>1;
	change(ls,pl,mid,l,r,x);
	change(rs,mid+1,pr,l,r,x);
	t[p]=max(t[ls],t[rs]);
}

signed main(){
//	freopen("P3709_2.in","r",stdin);
//	freopen("a.out","w",stdout);
    ios::sync_with_stdio(false);
	read();
	
	int l=0,r=0;
	t[0]=-1;
	while(1){
		while(t[1]<m&&r<=n){
			r++;
			change(1,1,2*n,a[r].l,a[r].r,1);
		}
		if(t[1]<m){
			break;
		}
		while(t[1]>=m&&l<=n){
			l++;
			change(1,1,2*n,a[l].l,a[l].r,-1);
		}
		
		ans=min(ans,getsum(l,r));
	}
	
	if(ans==2e9){
		cout<<-1;
	}
	else{
		cout<<ans;
	}
    return 0;
}
posted @ 2024-11-14 11:16  sad_lin  阅读(37)  评论(0)    收藏  举报