洛谷 1712 BZOJ 4653 [NOI2016]区间
【题解】
先把区间按照未离散化的长度排序,保存区间长度,然后离散化区间端点。每次把区间覆盖的点的覆盖次数加1,如果某个点被覆盖次数大于等于m,就从前往后开始删除区间直到没有一个点被覆盖的次数大于等于m,然后继续加入区间。边做边维护答案即可。
1 #include<cstdio> 2 #include<algorithm> 3 #define N 500010 4 #define rg register 5 #define ls (u<<1) 6 #define rs (u<<1|1) 7 using namespace std; 8 int n,m,b[N<<1],ans=2e9; 9 struct tree{ 10 int l,r,mx,del; 11 }a[N<<3]; 12 struct interval{ 13 int l,r,len; 14 }itv[N]; 15 inline int read(){ 16 int k=0,f=1; char c=getchar(); 17 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 18 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 19 return k*f; 20 } 21 inline int min(int x,int y){ 22 return x<y?x:y; 23 } 24 inline bool cmp(interval a,interval b){ 25 return a.len<b.len; 26 } 27 void build(int u,int l,int r){ 28 a[u].l=l; a[u].r=r; int mid=(l+r)>>1; 29 if(l<r) build(ls,l,mid),build(rs,mid+1,r); 30 } 31 void update(int u,int l,int r,int del){ 32 if(l<=a[u].l&&a[u].r<=r){ 33 a[u].del+=del; a[u].mx+=del; return; 34 } 35 int d=a[u].del; a[u].del=0; 36 a[ls].del+=d; a[rs].del+=d; 37 a[ls].mx+=d; a[rs].mx+=d; 38 int mid=(a[u].l+a[u].r)>>1; 39 if(l<=mid) update(ls,l,r,del); 40 if(r>mid) update(rs,l,r,del); 41 a[u].mx=max(a[ls].mx,a[rs].mx); 42 } 43 int main(){ 44 n=read(); m=read(); 45 for(rg int i=1;i<=n;i++) 46 itv[i].l=b[i]=read(),itv[i].r=b[i+n]=read(),itv[i].len=itv[i].r-itv[i].l; 47 sort(b+1,b+1+(n<<1)); int n2=unique(b+1,b+1+(n<<1))-b-1; 48 for(rg int i=1;i<=n;i++) 49 itv[i].l=lower_bound(b+1,b+1+n2,itv[i].l)-b, 50 itv[i].r=lower_bound(b+1,b+1+n2,itv[i].r)-b; 51 sort(itv+1,itv+1+n,cmp); 52 build(1,1,n2); 53 int front=1; 54 for(rg int rear=1;rear<=n;rear++){ 55 update(1,itv[rear].l,itv[rear].r,1); 56 while(a[1].mx>=m&&front<=rear){ 57 ans=min(ans,itv[rear].len-itv[front].len); 58 update(1,itv[front].l,itv[front].r,-1); 59 front++; 60 } 61 } 62 if(ans==2e9) puts("-1"); 63 else printf("%d\n",ans); 64 return 0; 65 }