1. 程式人生 > 其它 >[NOI2016] 區間

[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");
}