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