uoj222 NOI2016—区间
Posted MashiroSky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uoj222 NOI2016—区间相关的知识,希望对你有一定的参考价值。
http://uoj.ac/problem/222 (题目链接)
题意:有n个区间,当有m个区间有公共部分时,求m个区间长度的最大值与最小值之差的最小值。
Solution
线段树+滑动窗口。这道题很好做,可是在考场上就差一点点,我愣是没想出来。
先将区间按长度排序,保证它们的长度是递增的,这样就可以滑动窗口了。将区间的端点离散化后,用线段树维护每个节点被覆盖的次数,记录当前区间被覆盖次数最多的点被覆盖多少次,当次数达到要求是更新答案,将头指针向后移动。
代码:
// uoj222 #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #define MOD 1000000007 #define inf 2147483640 #define LL long long #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout); using namespace std; inline int getint() { int x=0,f=1;char ch=getchar(); while (ch>‘9‘ || ch<‘0‘) {if (ch==‘-‘) f=-1;ch=getchar();} while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();} return x*f; } const int maxn=10000010; struct data {int l,r,len;}a[maxn]; struct tree {int l,r,s,tag;}tr[maxn<<2]; int b[maxn<<2],n,m,ans,cnt; bool cmp(data a,data b) { return a.len<b.len; } void build(int k,int s,int t) { tr[k].l=s;tr[k].r=t;tr[k].s=tr[k].tag=0; if (s==t) return; int mid=(s+t)>>1; build(k<<1,s,mid); build(k<<1|1,mid+1,t); } void pushdown(int k) { tr[k<<1].s+=tr[k].tag;tr[k<<1|1].s+=tr[k].tag; tr[k<<1].tag+=tr[k].tag;tr[k<<1|1].tag+=tr[k].tag; tr[k].tag=0; } void update(int k,int s,int t,int val) { int l=tr[k].l,r=tr[k].r; if (tr[k].tag!=0) pushdown(k); if (s==l && r==t) {tr[k].tag+=val;tr[k].s+=val;return;} int mid=(l+r)>>1; if (t<=mid) update(k<<1,s,t,val); else if (s>mid) update(k<<1|1,s,t,val); else update(k<<1,s,mid,val),update(k<<1|1,mid+1,t,val); tr[k].s=max(tr[k<<1].s,tr[k<<1|1].s); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d%d",&a[i].l,&a[i].r); b[++cnt]=a[i].l;b[++cnt]=a[i].r; a[i].len=a[i].r-a[i].l; } sort(a+1,a+1+n,cmp);sort(b+1,b+1+cnt); build(1,1,cnt); for (int i=1;i<=n;i++) a[i].l=lower_bound(b+1,b+1+cnt,a[i].l)-b,a[i].r=lower_bound(b+1,b+1+cnt,a[i].r)-b; ans=inf; int L=1,R=1; while (R<=n) { update(1,a[R].l,a[R].r,1); while (tr[1].s>=m) { ans=min(ans,a[R].len-a[L].len); update(1,a[L].l,a[L].r,-1); L++; } R++; } printf("%d",ans<inf?ans:-1); return 0; }
以上是关于uoj222 NOI2016—区间的主要内容,如果未能解决你的问题,请参考以下文章
[UOJ#220][BZOJ4651][Noi2016]网格