[NOI2016] 區間
阿新 • • 發佈:2021-06-16
不是很會做。
大概是以前沒有見過這種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"); }