[NOI2016]区间

链接:https://www.luogu.org/problemnew/show/P1712

题解:

显然是个滑动窗口的问题,用线段树维护最大值即可

注意:离散化时空间要开2倍,最大值初始赋值为2e9比较好

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 500100
#define mm 1999999999
#define lll long long
lll n,m;
struct re{
    lll a,b,len,c,d;
}a[maxn],b[maxn*2];
bool cmp(re x,re y)
{
  if (x.len>y.len) return(true); else return(false);    
} 
struct ree
{
    lll h,t,x,lazy;
}p[maxn*4];
void updata(lll x)
{
    p[x].x=max(p[x*2].x,p[x*2+1].x);
}
#define mid (h+t)/2
void build(lll x,lll h,lll t)
{
    p[x].h=h; p[x].t=t;
    p[x].x=0; p[x].lazy=0;
    if (h==t) return;
    build(x*2,h,mid); build(x*2+1,mid+1,t);
}
void down(lll x)
{
    if (p[x].lazy)
    {
        p[x].x+=p[x].lazy;
        if (p[x].h!=p[x].t)
        {
            p[x*2].lazy+=p[x].lazy;
            p[x*2+1].lazy+=p[x].lazy;
        }
        p[x].lazy=0;
    }
}
void change (lll x,lll h,lll t,lll sum)
{
    down(x);
    if (p[x].h>t||p[x].t<h) return;
    if (h<=p[x].h&&p[x].t<=t)
    {
        p[x].lazy+=sum; down(x);
        return;
    }
    change(x*2,h,t,sum);change(x*2+1,h,t,sum);
    updata(x);
}
lll query(lll x,lll h,lll t)
{
    down(x);
    if (p[x].h>t||p[x].t<h) return(0);
    if (h<=p[x].h&&p[x].t<=t)
    {
        return(p[x].x);
    }
    return(max(query(x*2,h,t),query(x*2+1,h,t)));
}
int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  for (lll i=1;i<=n;i++)
  {
      cin>>a[i].a>>a[i].b;
      a[i].len=a[i].b-a[i].a;
  }
  sort(a+1,a+1+n,cmp);
  for (lll i=1;i<=n;i++)
  {
      b[i*2-1].a=i*2-1; b[i*2].a=i*2;
      b[i*2-1].len=a[i].a; b[i*2].len=a[i].b;
  }    
  sort(b+1,b+2*n+1,cmp);
  lll ll=0; b[0].len=-mm;
  for (lll i=1;i<=2*n;i++)
  {
      if (b[i].len!=b[i-1].len) ll++;
      if (b[i].a%2==0) a[(b[i].a-1)/2+1].c=ll;
      else a[(b[i].a-1)/2+1].d=ll;
  }
  build(1,1,ll);
  lll h=0,t=0;
  lll ans=mm;
  //for (lll i=1;i<=2*n;i++) cout<<b[i].len<" ";
  //for (lll i=1;i<=n;i++) cout<<endl<<a[i].a<<" "<<a[i].b<<" "<<a[i].c<<" "<<a[i].d; 
  while (t<n)
  {
      h++;
      if (h!=1)
      {
      change(1,a[h-1].c,a[h-1].d,-1);    
    }
      while (query(1,1,ll)<m&&t<=n)
      {
          t++; change(1,a[t].c,a[t].d,1);
    }
    if (t<=n) ans=min(ans,a[h].len-a[t].len);
  }
  if (ans!=mm)cout<<ans; else cout<<-1;
} 

 

posted @ 2018-02-01 12:52  尹吴潇  阅读(125)  评论(0编辑  收藏  举报