目录
显示
题目链接
https://www.luogu.com.cn/problem/P1712
题解
这个问题求的是两个区间长度的差,因此我们可以考虑排序后用双指针维护连续区间集合。
我们将右指针不断向右移动,加入新的区间,当有一个点被区间覆盖超过 \(M\) 次时统计答案,并移动左指针删除区间。
维护一个区间被覆盖的次数可以用线段树方便地完成。
#include <iostream> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; struct SegT { int maxa,tag; }se[4000005]; struct seg { int l,r,len; bool operator<(const seg&a)const { return len<a.len; } }s[500005]; int p[1000005],cnt; void pushup(int root) { se[root].maxa=max(se[root<<1].maxa,se[root<<1|1].maxa); } void pushdown(int root) { se[root<<1].maxa+=se[root].tag; se[root<<1|1].maxa+=se[root].tag; se[root<<1].tag+=se[root].tag; se[root<<1|1].tag+=se[root].tag; se[root].tag=0; } void update(int root,int cl,int cr,int l,int r,int x) { if(cr<l||r<cl)return; if(l<=cl&&cr<=r) { se[root].maxa+=x; se[root].tag+=x; return; } pushdown(root); int mid=(cl+cr)>>1; update(root<<1,cl,mid,l,r,x); update(root<<1|1,mid+1,cr,l,r,x); pushup(root); } int main() { int n,m,ans=INF; cin>>n>>m; for(int i=1;i<=n;i++) { cin>>s[i].l>>s[i].r; p[++cnt]=s[i].l; p[++cnt]=s[i].r; s[i].len=s[i].r-s[i].l; } sort(p+1,p+cnt+1); cnt=unique(p+1,p+cnt+1)-p-1; for(int i=1;i<=n;i++) { s[i].l=lower_bound(p+1,p+cnt+1,s[i].l)-p; s[i].r=lower_bound(p+1,p+cnt+1,s[i].r)-p; } sort(s+1,s+n+1); int l=1; for(int r=1;r<=n;r++) { update(1,1,cnt,s[r].l,s[r].r,1); while(se[1].maxa>=m) { ans=min(ans,s[r].len-s[l].len); update(1,1,cnt,s[l].l,s[l].r,-1); l++; } } if(ans==INF)cout<<-1<<endl; else cout<<ans<<endl; return 0; }