对前几个点 我们可以采用暴力枚举 选择区间的方案 暴力给每个点的权值+1 ,
时间复杂度为 O(2^n(m/2n+1) ) 应该有错
看起来这个算法很没用 也的确很没用
这个算法也有很大的优化空间 :
我们可以看到 时间复杂度 中 “2^n” 是一个很难受的项
我们首先考录消去它
对此 , 我们可以采用尺取法 不知道尺取法的自行解决
由于 每个区间对答案的贡献 仅与它的长度有关 , 与其他一切无关
所以 , 我们可以 把每一个区间 按长度 进行排序
这样的话 , 我们就可以进行 尺取法 了
设 “尺” 的左端点 为 L ,右端点 为 R
暴力给 每一个点的点权+1 是很费时间的 猪都知道
我们可以用线段树来优化
线段树 在本题的优点 有两个方面:
1. 加速 区间点权+1 ( 区间+ 操作)
2. 维护 当前点权最大点 的 点权
有了这线段树 , 时间复杂度 就能 再 下降一个档次
成为 我们可以接受 的 复杂度
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define MAXN 500005 using namespace std; int n,m,cnt,v[3*MAXN]; int ans=2100000000; struct node { int l,r,len; }f[MAXN]; struct Tree { int l,r; int val; int add; }tree[10*MAXN]; bool cmp(const node k,const node t) { return k.len<t.len; } void push(int now) { tree[now*2].add+=tree[now].add; tree[now*2].val+=tree[now].add; tree[now*2+1].val+=tree[now].add; tree[now*2+1].add+=tree[now].add; tree[now].add=0; } void build(int l,int r,int now) { tree[now].l=l; tree[now].r=r; tree[now].add=0; if (l==r) { tree[now].val=0; return; } int mid=(l+r)>>1; build(l,mid,now*2); build(mid+1,r,now*2+1); tree[now].val=max(tree[now*2].val, tree[now*2+1].val); return; } void change(int now,int l,int r,int k) { if(tree[now].l==l && tree[now].r==r) { tree[now].add+=k; tree[now].val+=k; return; } push(now); int mid=(tree[now].l+tree[now].r)>>1; if (r<=mid) change(now*2,l,r,k); if (l>mid) change(now*2+1,l,r,k); if (l<=mid && r>mid) { change(now*2,l,mid,k); change(now*2+1,mid+1,r,k); } tree[now].val=max(tree[now*2].val, tree[now*2+1].val); } int main() { scanf("%d %d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d %d",&f[i].l,&f[i].r); f[i].len=f[i].r-f[i].l+1; v[++cnt]=f[i].l; v[++cnt]=f[i].r; } sort(v+1,v+cnt+1); int x=unique(v+1,v+cnt+1)-(v+1); for (int i=1;i<=n;i++) { f[i].l=lower_bound(v+1,v+x+1,f[i].l)-v;
f[i].r=lower_bound(v+1,v+x+1,f[i].r)-v; } build(1,x+100,1); sort(f+1,f+n+1,cmp); int now=1; for (int i=1;i<=n;i++) { change(1,f[i].l,f[i].r,1); while (tree[1].val>=m && now<=i) { ans=min(ans,f[i].len-f[now].len); change(1,f[now].l,f[now].r,-1); now++; } } if (ans!=2100000000) printf("%d\n",ans); else puts("-1"); return 0; }
原文:https://www.cnblogs.com/maowuyou/p/11913822.html