首先将区间按长度排序后离散化端点(这里的“长度”指的是离散化之前区间的实际长度)
然后模拟一个队列,区间按排好的顺序依次进入,直到某个点被覆盖了M次。之后依次出队,直到所有点都被覆盖小于M次
修改和询问覆盖次数可以用线段树实现
//C++11 code #include <cstdio> #include <cstring> #include <algorithm> ; const int inf=0x7f7f7f7f; struct Range { int left,right; int len; void assign(int l,int r) { left=l; right=r; len=r-l; } }; struct SegTree { struct Node { ; //max-val ; int total() { return val+tag; } }; Node node[maxN<<]; int size; int _val; void update(int cur,int right) { node[cur].val = std::max(node[cur+].total(),node[right].total()); } void add(int L,int R,int val) { _val=val; __add(,L,R+,,size); } void __add(int cur,int rL,int rR,int nL,int nR) { if(rL<=nL && rR>=nR) { node[cur].tag+=_val; return; } ; ); ,rL,rR,nL,mid); if(rR>mid) __add(right,rL,rR,mid,nR); update(cur,right); } ].total(); } }; Range rg[maxN]; SegTree segt; int N,M; ]; int valNum; void input() { scanf("%d%d",&N,&M); int tl,tr; ;i<N;i++) { scanf("%d%d",&tl,&tr); buf[i<<]=tl; buf[(i<<)+]=tr; rg[i].assign(tl,tr); } } void discretize() { std::sort(buf,buf+(N<<)); valNum=std::unique(buf,buf+(N<<))-buf; ;i<N;i++) { rg[i].left=std::lower_bound(buf,buf+valNum,rg[i].left)-buf; rg[i].right=std::lower_bound(buf,buf+valNum,rg[i].right)-buf; } } int solve() { int res=inf; auto cmpIdx=[](const Range& A,const Range& B)->bool { return A.len<B.len; }; std::sort(rg,rg+N,cmpIdx); discretize(); segt.size=valNum; ,tail=-; ) { while((++head)<N && segt.askAll()<M) segt.add(rg[head].left,rg[head].right,); if(segt.askAll()<M) break; else --head; while(segt.askAll()==M) { ++tail; res=std::min(res,rg[head].len-rg[tail].len); segt.add(rg[tail].left,rg[tail].right,-); } } :res; } int main() { input(); printf("%d\n",solve()); ; }