洛谷 P1712 [NOI2016] 區間(尺取法、線段樹)
阿新 • • 發佈:2021-10-18
傳送門
解題思路
考慮尺取法。
將所有區間按照長度從小到大排序,然後tow-pointers在保證區間最大值>=m的情況下不斷維護區間+1/-1。
用線段樹維護。
AC程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> using namespace std; const int maxn=500005; int a[maxn*2],cnt,n,m,ans=2e9,d[maxn*6],lazy[maxn*6]; struct node{ int l,r,len; bool operator <(const node a)const{ return len<a.len; } }q[maxn]; inline void pushup(int id){ d[id]=max(d[id*2],d[id*2+1]); } inline void pushdown(int id){ if(lazy[id]){ lazy[id*2]+=lazy[id]; lazy[id*2+1]+=lazy[id]; d[id*2]+=lazy[id]; d[id*2+1]+=lazy[id]; lazy[id]=0; } } void update(int id,int l,int r,int x,int y,int v){ if(x<=l&&r<=y){ d[id]+=v; lazy[id]+=v; return; } int mid=(l+r)/2; pushdown(id); if(x<=mid) update(id*2,l,mid,x,y,v); if(y>mid) update(id*2+1,mid+1,r,x,y,v); pushup(id); } int main(){ ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++){ cin>>q[i].l>>q[i].r; a[++cnt]=q[i].l; a[++cnt]=q[i].r; q[i].len=q[i].r-q[i].l; } sort(q+1,q+n+1); sort(a+1,a+cnt+1); cnt=unique(a+1,a+cnt+1)-a-1; for(int i=1;i<=n;i++){ q[i].l=lower_bound(a+1,a+cnt+1,q[i].l)-a; q[i].r=lower_bound(a+1,a+cnt+1,q[i].r)-a; } int l=0; for(int i=1;i<=n;i++){ update(1,1,cnt,q[i].l,q[i].r,1); while(l<=i&&d[1]>=m){ if(l) update(1,1,cnt,q[l].l,q[l].r,-1); ans=min(q[i].len-q[l].len,ans); l++; } } cout<<(ans==2e9?-1:ans); return 0; }