P1712 [NOI2016]区间
题目描述
Solution
尺取法+线段树
一个显然的想法是按区间长度排序。
每一次多选取一个区间相当于区间覆盖次数加1,每一次少选取一个区间就有区间覆盖次数减1。
可以用线段树维护区间覆盖次数的最大值。
于是转化成了一个Two-Pointers的问题,尺取法扫一遍即可。
时间复杂度 。
Code
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1e6+50;
inline int read()
{
int x=0,f=1; char c=getchar();
while (c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
return x*f;
}
struct qnode{int opt,id,x,color; } q[MAXN];
int compareq(qnode x,qnode y) { return (x.x<y.x)||(x.x==y.x&&x.opt<y.opt); }
struct anode{int lpre,rpre,lnow,rnow,len; } a[MAXN];
int comparea(anode x,anode y){ return x.len<y.len; }
struct Segment_Tree
{
struct segnode{int l,r,tag,mx; } tree[MAXN<<2];
void up(int x){ tree[x].mx=max(tree[x<<1].mx,tree[x<<1|1].mx); }
void down(int x)
{
if (tree[x].tag!=0)
{
int q=tree[x].tag;
tree[x<<1].tag+=q,tree[x<<1].mx+=q;
tree[x<<1|1].tag+=q,tree[x<<1|1].mx+=q;
tree[x].tag=0;
}
}
void build(int x,int l,int r)
{
if ((tree[x].l=l)==(tree[x].r=r)) return;
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
int query(int x,int l,int r)
{
if (tree[x].l>=l&&tree[x].r<=r) return tree[x].mx;
down(x);
int mid=(tree[x].l+tree[x].r)>>1;
if (r<=mid) return query(x<<1,l,r);
else if (l>mid) return query(x<<1|1,l,r);
else return max(query(x<<1,l,mid),query(x<<1|1,mid+1,r));
}
void change(int x,int l,int r,int y)
{
if (tree[x].l>=l&&tree[x].r<=r)
{
tree[x].mx+=y;
tree[x].tag+=y;
return;
}
down(x);
int mid=(tree[x].l+tree[x].r)>>1;
if (r<=mid) change(x<<1,l,r,y);
else if (l>mid) change(x<<1|1,l,r,y);
else change(x<<1,l,mid,y),change(x<<1|1,mid+1,r,y);
up(x);
}
} segment;
int main()
{
int n=read(),m=read(),num=0;
for (int i=1;i<=n;i++)
{
int l=read(),r=read();
q[++num]=(qnode){0,i,l,0};
q[++num]=(qnode){1,i,r,0};
}
sort(q+1,q+num+1,compareq);
q[0].x=-1;
for (int i=1;i<=num;i++)
{
q[i].color=q[i-1].color+(q[i].x!=q[i-1].x);
if (q[i].opt==0) a[q[i].id].lpre=q[i].x,a[q[i].id].lnow=q[i].color;
if (q[i].opt==1) a[q[i].id].rpre=q[i].x,a[q[i].id].rnow=q[i].color,a[q[i].id].len=a[q[i].id].rpre-a[q[i].id].lpre+1;
}
sort(a+1,a+n+1,comparea);
cout<<endl;
for (int i=1;i<=n;i++) cout<<a[i].lpre<<" "<<a[i].rpre<<" "<<a[i].lnow<<" "<<a[i].rnow<<" "<<a[i].len<<endl;
segment.build(1,1,q[num].color);
int ans=INF;
for (int l=1,r=1;r<=n;r++)
{
segment.change(1,a[r].lnow,a[r].rnow,1);
while (segment.query(1,1,q[num].color)>=m)
{
ans=min(ans,a[r].len-a[l].len);
segment.change(1,a[l].lnow,a[l].rnow,-1);
l++;
}
}
if (ans==INF) puts("-1");
else printf("%d\n",ans);
return 0;
}