题目大意

有\(n\)(\(n\leq 5*10^5\))个闭区间\([L_1,R_1],[L_2,R_2],...,[L_n,R_n]\)(\(\forall i\in [1,n],0\leq L_i\leq R_i\leq 10^9\))

要选取\(m\)个区间,使这\(m\)个区间的交不为空,方案的花费为被选中的区间中 长度最长的区间的长度 减 长度最短的区间的长度

求花费最小的方案,或判断无解

题解

将\(n\)个区间按区间长度排序

问题转化成对于所有满足存在一点被\([L_l,R_l],[L_{l+1},R_{l+1}],...,[L_r,R_r]\)覆盖不少于\(m\)次的\([l,r]\)中,使\(R_r-L_r-R_l+L_l\)最小

发现将合法的\([l,r]\)中的\(r\)右移时,要想产生更优的解,\(l\)也得右移,也就是单调性

那就可以从小到大枚举\(r\),维护当前最优解的\(l\)的位置,用权值线段树或离散化后用线段树判断是否有一点被覆盖超过\(m\)次

但是\(n\)比较大,用权值线段树可能会被卡

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define maxn 500010
#define ls (u<<1)
#define rs (u<<1|1)
#define mi (l+r>>1)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int n,ext[maxn<<1],cnte,tr[maxn<<3],mk[maxn<<3],ans=-1,m;
struct node{int l,r;}nd[maxn];
bool cmp(node x,node y){return x.r-x.l<y.r-y.l;}
void mark(int u,int k){tr[u]+=k,mk[u]+=k;}
void pd(int u){if(mk[u])mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}
void pu(int u){tr[u]=max(tr[ls],tr[rs]);}
void add(int u,int l,int r,int x,int y,int k)
{
if(x<=l&&r<=y)return mark(u,k);
pd(u);
if(x<=mi)add(ls,l,mi,x,y,k);
if(y>mi)add(rs,mi+1,r,x,y,k);
return pu(u);
}
int getr(int x)
{
int l=1,r=cnte,ans=cnte+1;
while(l<=r)
{
int mid=mi;
if(ext[mid]<x)l=mid+1;
else if(ext[mid]>x)r=mid-1;
else ans=min(ans,mid),r=mid-1;
}
return ans;
}
int jud(int i,int j)
{
add(1,1,cnte,getr(nd[j].l),getr(nd[j].r),-1);
int x=tr[1];
if(x>=m)return 1;
add(1,1,cnte,getr(nd[j].l),getr(nd[j].r),1);return 0;
}
signed main()
{
n=read(),m=read();
rep(i,1,n)nd[i].l=read(),nd[i].r=read(),ext[++cnte]=nd[i].l,ext[++cnte]=nd[i].r;
sort(nd+1,nd+n+1,cmp),sort(ext+1,ext+cnte+1);int j=1;
rep(i,1,n)
{
add(1,1,cnte,getr(nd[i].l),getr(nd[i].r),1);
while(jud(i,j)&&j<=i)j++;
if(tr[1]>=m)ans=(ans==-1)?(nd[i].r-nd[i].l-nd[j].r+nd[j].l):min(ans,(nd[i].r-nd[i].l-nd[j].r+nd[j].l));
}
write(ans);
return 0;
}

并不对劲的bzoj4651:loj2086:uoj222:p1712:[NOI2016]区间的更多相关文章

  1. Luogu P1712 [NOI2016]区间(线段树)

    P1712 [NOI2016]区间 题意 题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间, ...

  2. 【题解】P1712 [NOI2016]区间(贪心+线段树)

    [题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...

  3. 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化

    洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...

  4. 并不对劲的bzoj4651:loj2084:uoj220:p1173:[NOI2016]网格

    题目大意 有一个\(n*m\)(\(n,m\leq10^9\))的网格,每个格子是空地或障碍(\(障碍数\leq10^5\)) 定义两块空地连通,当且仅当它们是"相邻的两块空地"或 ...

  5. 【uoj222】 NOI2016—区间

    http://uoj.ac/problem/222 (题目链接) 题意 有n个区间,当有m个区间有公共部分时,求m个区间长度的最大值与最小值之差的最小值. Solution 线段树+滑动窗口.这道题很 ...

  6. BZOJ4653 & 洛谷1712 & UOJ222:[NOI2016]区间——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4653 https://www.luogu.org/problemnew/show/P1712 ht ...

  7. P1712 [NOI2016]区间

    题目描述 在数轴上有 NN 个闭区间 [l_1,r_1],[l_2,r_2],...,[l_n,r_n][l1​,r1​],[l2​,r2​],...,[ln​,rn​] .现在要从中选出 MM 个区 ...

  8. 洛谷 P1712 [NOI2016]区间(线段树)

    传送门 考虑将所有的区间按长度排序 考虑怎么判断点被多少区间覆盖,这个可以离散化之后用一棵权值线段树来搞 然后维护两个指针$l,r$,当被覆盖次数最多的点的覆盖次数小于$m$时不断右移$r$,在覆盖次 ...

  9. luogu P1712 [NOI2016]区间

    题目描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...

随机推荐

  1. C# CreateDataTable

    public DataTable CreateDataTable()         {             DataTable dataTable = new DataTable();      ...

  2. MacOS & iOS

    MacOS & iOS https://github.com/qinjx/30min_guides/blob/master/ios.md https://www.cnblogs.com/xgq ...

  3. 【多校训练2】HDU 6047 Maximum Sequence

    http://acm.hdu.edu.cn/showproblem.php?pid=6047 [题意] 给定两个长度为n的序列a和b,现在要通过一定的规则找到可行的a_n+1.....a_2n,求su ...

  4. bzoj 3223 文艺平衡树 splay 区间翻转

    Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 17715  Solved: 7769[Submit][Status][ ...

  5. 新版VS-code如何自动换行?

    文件  -> 首选项 -> 设置 -> 编辑器 找到 // 控制折行方式.可以选择: - "off" (禁用折行), - "on" (视区折行 ...

  6. Android广播Broadcast

    Android Broadcast简单认识 Broadcast是应用程序间传输信息的一种机制,BroadcastReceiver是对发送出来的广播(Broadcast)进行过滤并接收相应的一类组件. ...

  7. msp430入门编程37

    msp430中C语言的可移植--屏蔽实现细节

  8. Java子类重写父类方法注意问题收集(转)

    子类不能重写父类的静态方法,私有方法.即使你看到子类中存在貌似是重写的父类的静态方法或者私有方法,编译是没有问题的,但那其实是你重新又定义的方法,不是重写.具体有关重写父类方法的规则如下: 重写规则之 ...

  9. sqlite中常见的问题总结

    一.sqlite中不能使用日期进行相减,执行结果无效 例如:SELECT count(*) as cnt FROM DayBanalces WHERE (date(ofDay)- date('2013 ...

  10. Windows下SVN服务器及客户端的使用

    原文地址:windows下配置VisualSVN Server服务器 作者:Deem_passion 下载安装文件: 服务端安装文件:VisualSVN-Server-1.6.2 客户端安装文件:To ...