NOI 2016 区间
我们可以贪心的做。
如果不考虑如何判一个点被覆盖K次的话。这就是一道经典问题。
我们先把线段排序,那么我们考虑一个队列。
我们发现我们先把小的塞进队尾,等到塞的足够多(存在一个点被覆盖了K次)我们就更新答案并把队尾弹出。
我们可以用线段树维护点的覆盖次数K。
第一次写标记永久化,#define max写炸调半天,果然老年选手该退役了。
#include<bits/stdc++.h> #define N 500007 #define SIZ 14000007 #define sight(c) ('0'<=c&&c<='9') #define INF 1000000007 using namespace std; struct Node{ int a,b,len; inline bool operator < (const Node A)const{ return len<A.len; } }p[N]; inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);} inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); } inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); } int root,ls[SIZ],rs[SIZ],mas[SIZ],lazy[SIZ],tot,n,m,ans=INF,tog; void add(int &node,int l,int r,int LL,int RR,int dla){ if (!node) node=++tog; if (LL<=l&&r<=RR) { mas[node]+=dla,lazy[node]+=dla;return;} int Mid=l+r>>1; if (LL<=Mid) add(ls[node],l,Mid,LL,RR,dla); if (RR> Mid) add(rs[node],Mid+1,r,LL,RR,dla); mas[node]=max(mas[ls[node]],mas[rs[node]])+lazy[node]; } #undef max int main() { read(n); read(m); for (int i=1;i<=n;i++) read(p[i].a),read(p[i].b),p[i].len=p[i].b-p[i].a; sort(p+1,p+n+1); for (int i=1;i<=n;i++) { add(root,0,INF,p[i].a,p[i].b,1); while (mas[1]>=m) { ans=min(ans,p[i].len-p[++tot].len); //cerr<<"sb"<<endl; add(root,0,INF,p[tot].a,p[tot].b,-1); } } writeln(ans==INF?-1:ans); return 0; }