正解:线段树
解题报告:
$umm$很久以前做的了来补个题解$QwQ$
考虑给每个区间按权值($r-l$从大往小排序,依次加入,然后考虑如果有一个位置被覆盖次数等于$m$了就可以把权值最大的那个删去直到被覆盖次数小于$m$,顺便更新答案
然后就做完辣!$QwQ$
放下代码趴,然后因为是去年的代码了所以码风可能有点丑,,,懒得改了$QwQ$
$over$
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; int n,m,b[2000009],c[2000009],d[1000009],mx[4000009],add[4000009],l=1,r=0,ans=0x7fffffff,num; struct seg { int x,y,len; inline bool operator <(const seg& rhs) const { return len>rhs.len; } }a[500009]; inline int read() { char ch=getchar();int x=0; while(ch>'9' || ch<'0')ch=getchar(); while(ch<='9' && ch>='0')x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return x; } inline void ins(int l,int r,int x,int y,int k,int v) { if (x<=l&&y>=r) { add[k]+=v; mx[k]+=v; return; } int mid=l+r>>1; if (x<=mid) ins(l,mid,x,y,k<<1,v); if (y>mid) ins(mid+1,r,x,y,k<<1|1,v); mx[k]=max(mx[k<<1],mx[k<<1|1]); mx[k]+=add[k]; } int low(int x) { int l=1,r=num,mid; while (l<r) { mid=(l+r)>>1; if (b[mid]>=x) r=mid; else l=mid+1; } return l; } int main() { n=read(),m=read(); num=0; for (int i=1;i<=n;i++) { a[i].x=read(); a[i].y=read(); a[i].len=a[i].y-a[i].x; b[++num]=a[i].x; b[++num]=a[i].y; } sort(a+1,a+n+1); sort(b+1,b+num+1); for (int i=1;i<=n;i++) a[i].x=low(a[i].x),a[i].y=low(a[i].y); for (int r=1;r<=n;r++) { ins(1,num,a[r].x,a[r].y,1,1); while (mx[1]>=m) { ans=min(ans,a[l].len-a[r].len); ins(1,num,a[l].x,a[l].y,1,-1); l++; } } if (ans!=0x7fffffff) printf("%d\n",ans); else printf("-1"); return 0; }View Code