[NOI2016] 区间

不是很会做。
大概是以前没有见过这种trick的原因。
自己想到了线段树维护出现点数,但是不会统计答案。

先分析一些东西:
首先因为只有(m)个区间要被选,且答案贡献为(max - min),可以考虑尺取。
感觉知道这个核心(trick)就能做了。
从小到大加入,线段树随便维护一下。

[NOI2016] 区间
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 500005

struct P{ll l,r,len;}e[N];

inline bool operator < (P a,P b){
	return a.len < b.len;
}

ll b[N << 2];
ll n,m;

int ma[N << 3],lazy[N << 3];

#define l(x) (x << 1)
#define r(x) (x << 1 | 1)
#define mid ((l + r) >> 1)

inline void up(int u){
	ma[u] = std::max(ma[l(u)],ma[r(u)]);
}

inline void down(int u){
	ma[l(u)] += lazy[u];
	ma[r(u)] += lazy[u];
	lazy[l(u)] += lazy[u];
	lazy[r(u)] += lazy[u];
	lazy[u] = 0;
}

inline void add(int u,int l,int r,int tl,int tr,int p){
//	std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<" "<<p<<std::endl;		
	if(tl <= l && r <= tr){
		ma[u] += p;
		lazy[u] += p;
//		std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<ma[u]<<" "<<p<<std::endl;		
		return ;
	}
	down(u);
	if(tl <= mid)
	add(l(u),l,mid,tl,tr,p);
	if(tr > mid)
	add(r(u),mid + 1,r,tl,tr,p);
	up(u);
//	std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<ma[u]<<" "<<p<<std::endl;
}

ll ans = 0x3f3f3f3f;

int main(){
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= n;++i){
		scanf("%lld%lld",&e[i].l,&e[i].r);
		e[i].len = (e[i].r - e[i].l);
//		b[++b[0]] = e[i].l - 1;
		b[++b[0]] = e[i].l;
		b[++b[0]] = e[i].r;
//		b[++b[0]] = e[i].r + 1;
	}
	std::sort(b + 1,b + b[0] + 1);
	std::sort(e + 1,e + n + 1);
	b[0] = std::unique(b + 1,b + b[0] + 1) - b - 1;
	ll l = 1;
	ll r = 1;
	e[n + 1].len = 0x3f3f3f3f; 
//	for(int i = 1;i <= n;++i){
////		ll li = std::lower_bound(b + 1,b + b[0] + 1,e[i].l)- b;
////		ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[i].r)- b;
//		std::cout<<e[i].l<<" "<<e[i].r<<" "<<e[i].len<<" "<<std::endl;
//	}
	ll li = std::lower_bound(b + 1,b + b[0] + 1,e[1].l) - b;
	ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[1].r) - b;
	add(1,1,b[0],li,ri,1);
	while(l <= n && r <= n){
		while(ma[1] >= m){
			ll li = std::lower_bound(b + 1,b + b[0] + 1,e[l].l) - b;
			ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[l].r) - b;
			add(1,1,b[0],li,ri,-1);
//			std::cout<<l<<" "<<r<<" "<<e[r].len<<" "<<e[l].len<<" "<<ma[1]<<std::endl;
			ans = std::min(e[r].len - e[l].len,ans);			
			++l;
		}
		while(ma[1] < m){
			++r;
			if(r > n)
			break;
			ll li = std::lower_bound(b + 1,b + b[0] + 1,e[r].l) - b;
			ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[r].r) - b;
			add(1,1,b[0],li,ri,1);
		}
	}
	if(ans < 0x3f3f3f3f)
	std::cout<<ans<<std::endl;
	else
	puts("-1");
}
原文地址:https://www.cnblogs.com/dixiao/p/14891077.html