BZOJ

洛谷


\(Description\)

给定\(n\)个区间\([L_i,R_i]\),要选出尽量多的区间,并满足它们互不相交。求最多能选出多少个的区间以及字典序最小的方案。

\(n\leq2\times10^5\)。

\(Solution\)

第一问随便做。

对于第二问,从小到大枚举区间\([l_i,r_i]\),我们需要判断此时能不能选\([l_i,r_i]\)。

在之前选的区间中,设在\(i\)左边离\(l_i\)最近的区间的右端点是\(L\),在\(i\)右边离\(i\)最近的左端点是\(R\)。

显然要满足\(i\)与选中的区间不相交,有\(L<l_i\)且\(R>r_i\)。同时这两个区间在已选择的区间中一定是相邻的。可以\(set\)维护选择的区间,\(lower\_bound\)一次找出。

满足不相交后,还要满足最优。

令\(Ans(l,r)\)表示用在\([l,r]\)能选出的最多区间数。

那么能放入区间\([l_i,r_i]\)还要满足\(Ans(L+1,R-1)==Ans(L+1,l_i-1)+Ans(r_i+1,R-1)+1\)。很好理解。(只判\(i\)的前后缀显然不对啊)

如何求\(Ans(l,r)\)?

二分可以找到第一个满足\(l_i\geq l\)的区间\(i\),然后从\(i\)往后选,直到右端点\(>r\)。根据最简单的贪心,每选一个区间下一次选择的区间是确定的。so可以倍增,令\(f[i][j]\)表示从区间\(i\)开始选,选了\(2^j\)个区间后,停在哪个区间。

显然此时可以把完全包含其它区间的大区间给去掉,而且需要去掉(如果选到它们会影响答案)。


//21632kb	880ms
#include <set>
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 500000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e5+5,INF=1<<30; int cnt,Bit,L[N],R[N],f[18][N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node
{
int l,r,id;
bool operator <(const Node &x)const
{
return r==x.r?l>x.l:r<x.r;
}
}A[N],tmp[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline int Find(int x)
{
int l=1,r=cnt,mid;//cnt+1!(l may be greater than l[cnt])
while(l<r)
if(L[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
inline int Calc(int l,int r)
{
if(L[cnt]<l) return 0;
int p=Find(l);
if(R[p]>r) return 0;
int res=1;
for(int i=Bit; ~i; --i)
if(R[f[i][p]]<=r) res+=1<<i, p=f[i][p];
return res;
} int main()
{
const int n=read();
for(int i=1; i<=n; ++i) A[i]=tmp[i]=(Node){read(),read()};
std::sort(tmp+1,tmp+1+n), cnt=1;
for(int i=2; i<=n; ++i) if(tmp[i].l>tmp[cnt].l) tmp[++cnt]=tmp[i];//左右端点应该都是单调的
for(int i=1; i<=cnt; ++i) L[i]=tmp[i].l, R[i]=tmp[i].r;
L[cnt+1]=INF+1, R[0]=R[cnt+1]=INF+1;//INF+1!(后面会查l~INF)
for(int i=1,j=1; i<=cnt; ++i)
{
while(L[j]<=R[i]) ++j;
f[0][i]=j;
}
for(; 1<<Bit+1<=cnt; ++Bit);
for(int j=1; j<=Bit; ++j)
for(int i=1; i<=cnt; ++i)
f[j][i]=f[j-1][f[j-1][i]]; int ans=Calc(1,INF-1); printf("%d\n",ans);
std::set<Node> st;
st.insert((Node){0,0}), st.insert((Node){INF,INF});
for(int i=1,k=0; i<=n; ++i)
{
int l=A[i].l, r=A[i].r;
std::set<Node>::iterator it=st.lower_bound(A[i]);
int R=(*it).l; if(r>=R) continue;
int L=(*(--it)).r; if(l<=L) continue;
if(Calc(L+1,R-1)==Calc(L+1,l-1)+Calc(r+1,R-1)+1)
if(++k!=ans) printf("%d ",i), st.insert(A[i]);
else {printf("%d",i); break;}
} return 0;
}

BZOJ.1178.[APIO2009]会议中心(贪心 倍增)的更多相关文章

  1. BZOJ1178 APIO2009 会议中心 贪心、倍增

    传送门 只有第一问就比较水了 每一次贪心地选择当前可以选择的所有线段中右端点最短的,排序之后扫一遍即可. 考虑第二问.按照编号从小到大考虑每一条线段是否能够被加入.假设当前选了一个区间集合\(T\), ...

  2. [APIO2009]会议中心(贪心)

    P3626 [APIO2009]会议中心 题目描述 Siruseri 政府建造了一座新的会议中心.许多公司对租借会议中心的会堂很 感兴趣,他们希望能够在里面举行会议. 对于一个客户而言,仅当在开会时能 ...

  3. [APIO2009]会议中心

    [APIO2009]会议中心 题目大意: 原网址与样例戳我! 给定n个区间,询问以下问题: 1.最多能够选择多少个不相交的区间? 2.在第一问的基础上,输出字典序最小的方案. 数据范围:\(n \le ...

  4. 【题解】[APIO2009]会议中心

    [题解][P3626 APIO2009]会议中心 真的是一道好题!!!刷新了我对倍增浅显的认识. 此题若没有第二份输出一个字典序的方案,就是一道\(sort+\)贪心,但是第二问使得我们要用另外的办法 ...

  5. bzoj 1178: [Apio2009]CONVENTION会议中心(少见做法掉落!)【贪心+二分】

    数组若干+手动二分一个的算法,bzoj rank8 ===============================废话分割线=================================== 我我 ...

  6. bzoj 1178 [Apio2009]CONVENTION会议中心

    这题好难啊! 我好菜啊! 思路:对于最多线段不相交, 我们可以按左端点sort之后,贪心取. 但是这个题要求选取的线段排序之后序号的字典序最小. 那么我们如果按序号贪心地从大往小往里放, 那么对于第k ...

  7. BZOJ1178 [Apio2009]CONVENTION会议中心 贪心 set

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1178 题意概括 一堆线段,现在取出最多条数,使其互不覆盖,并输出字典序最小的方案. 题解 这题好坑 ...

  8. BZOJ1178或洛谷3626 [APIO2009]会议中心

    BZOJ原题链接 洛谷原题链接 第一个问题是经典的最多不相交区间问题,用贪心即可解决. 主要问题是第二个,求最小字典序的方案. 我们可以尝试从\(1\to n\)扫一遍所有区间,按顺序对每一个不会使答 ...

  9. Luogu 3626 [APIO2009]会议中心

    很优美的解法. 推荐大佬博客 如果没有保证字典序最小这一个要求,这题就是一个水题了,但是要保证字典序最小,然后我就不会了…… 如果一条线段能放入一个区间$[l', r']$并且不影响最优答案,那么对于 ...

随机推荐

  1. Linux基础三:linux目录结构和目录文件的浏览、管理及维护

    目录文件的浏览.管理及维护(一) 1.Linux文件系统的层次结构 1)Linux文件系统的树状结构:在Linux或UNIX操作系统中,所有的文件和目录都被组织成一个以根节点开始的倒置的树状结构. 2 ...

  2. 前端生成pdf文件之pdfmake.js

    转载:点击查看原文 pdfmake.js是一个简单的生成pdf文件的插件. pdfmake.js     https://files.cnblogs.com/files/s313139232/pdfm ...

  3. ruby安装sass和compass步骤

    依赖ruby,所以需要安装Ruby 如何安装Ruby呢?在windows下通过RubyInstaller来安装,安装过程中需要选择第二项 1.ruby -v 2.gem install sass (如 ...

  4. druid配置oracle遇到: 未找到要求的 FROM 关键字 errorCode 923, state 42000

    2018年05月29日 16:41:17 阅读数:518 问题背景 项目要连接oracle数据,采用的是durid连接池,但是基本配置下来,运行时发现了这个错误. 方案 可能有的一个错误就是,拼凑sq ...

  5. Parameter 'name' not found. Available parameters are [arg1, arg0, param1, param2]

    解决方法: <select id="selectIf" resultType="student"> SELECT id,name,age,score ...

  6. JAVA 代码中使用中文的办法

    在编译代码中插入 -encoding UTF-8 示例: javac -encoding UTF-8 *.java

  7. 20165323 预备作业3 Linux安装及学习

    一.Linux安装 首先我按照老师所给的步骤下载了VirtualBox 5.2.6和Ubuntu 16.04.3.有流程下载很简单,但是在下载的过程中还是出现了一些问题. 1.VirtualBox 只 ...

  8. 从零开始学C#——数据类型(三)

    C#数据类型 在C#中,变量分为以下几种类型: 值类型 引用类型 指针类型 值类型 值类型变量可以直接分配给一个值,他们是从类System.ValucTpyc中派生. 值类型直接包含数据,比如int. ...

  9. .Net页面缓存OutPutCache详解

    一 它在Web.Config中的位置 <system.web> <!--页面缓存--> <caching> <outputCacheSettings> ...

  10. 移动端开发demo—移动端web相册(一)

    本文主要是介绍开发移动端web相册这样一案例用到的前置知识. 一.移动端样式 移动端更接近手机原生的方式. 如下是一个angular mobile的demo的例子: 移动端demo做成这样的好处: 在 ...