欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1178


题意概括

  一堆线段,现在取出最多条数,使其互不覆盖,并输出字典序最小的方案。


题解

  这题好坑。

  首先,注意一点,最后不能有多余的空格。

  第一问就是基础的线段覆盖。

  关键在于第二问。

  我们要准备一个函数—— Get_Ans(L,R),用来求解L~R这个区间内,最多可以取多少线段。

  这个可以O(log n)解决。前提是倍增预处理。

  然后就是关键部分。

  我们按照字典序从小到大,能选择就选择。

  怎么判断是否可以选择?只需要在之前选择的线段空隙中可以放这个线段,并且满足Get_Ans(这个线段到它左边的第一条线段之前)+Get_Ans(它到它右边的第一个线段之前)+1 = Get_Ans(他左右两端的),那么就可以放进去。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <set>
using namespace std;
const int N=200000+5,Inf=1e9;
struct seg{
int L,R;
bool operator < (const seg x) const {
if (L==x.L)
return R>x.R;
return L<x.L;
}
}s[N],s2[N];
int n,rn,Hash[N*2],hs,p[N][20],L[N];
bool alive[N],vis[N*2];
set <int> S;
void HASH(){
sort(Hash+1,Hash+hs+1);
int hs_=1;
for (int i=2;i<=hs;i++)
if (Hash[i]!=Hash[i-1])
Hash[++hs_]=Hash[i];
hs=hs_;
}
void Delete(){
for (int i=1;i<=n;i++)
s2[i]=s[i];
sort(s+1,s+n+1);
memset(alive,true,sizeof alive);
int MinR=Inf,n_=0;
for (int i=n;i>=1;i--)
if (MinR>s[i].R)
MinR=s[i].R;
else
alive[i]=0;
for (int i=1;i<=n;i++)
if (alive[i])
s[++n_]=s[i];
n=n_;
}
void Get_Pos(){
memset(p,0,sizeof p);
for (int i=1;i<=n;i++)
L[i]=s[i].L;
L[n+1]=Inf;
for (int i=1;i<=n;i++){
p[i][0]=upper_bound(L+1,L+n+2,s[i].R)-L;
if (p[i][0]==n+1)
p[i][0]=0;
}
for (int i=1;i<=18;i++)
for (int j=1;j<=n;j++)
p[j][i]=p[p[j][i-1]][i-1];
}
int Get_Ans(int Le,int Ri){
if (Le>Ri||Le>hs)
return 0;
int ans=1,pos=lower_bound(L+1,L+n+2,Le)-L;
if (pos>n||Ri<s[pos].R)
return 0;
for (int i=18;i>=0;i--){
if (!p[pos][i]||s[p[pos][i]].R>Ri)
continue;
pos=p[pos][i];
ans+=1<<i;
}
return ans;
}
int main(){
scanf("%d",&n),rn=n;
for (int i=1;i<=n;i++){
scanf("%d%d",&s[i].L,&s[i].R);
Hash[++hs]=s[i].L;
Hash[++hs]=s[i].R;
}
HASH();
for (int i=1;i<=n;i++){
s[i].L=lower_bound(Hash+1,Hash+hs+1,s[i].L)-Hash;
s[i].R=lower_bound(Hash+1,Hash+hs+1,s[i].R)-Hash;
}
Delete();
Get_Pos();
printf("%d\n",Get_Ans(1,hs));
S.clear();
S.insert(Inf),S.insert(-Inf);
bool empty_block=0;
for (int i=1;i<=rn;i++){
int now=*S.lower_bound(s2[i].L);
if (now==Inf||!vis[now]){
if (now<=s2[i].R)
continue;
int left=*--S.lower_bound(s2[i].L);
int right=*S.lower_bound(s2[i].R);
int val=Get_Ans(left+1,s2[i].L-1)+1+Get_Ans(s2[i].R+1,right-1);
if (val<Get_Ans(left+1,right-1))
continue;
S.insert(s2[i].L);
S.insert(s2[i].R);
if (s2[i].L!=s2[i].R)
vis[s2[i].R]=1;
if (empty_block)
putchar(' ');
printf("%d",i);
empty_block=1;
}
}
return 0;
}

  

BZOJ1178 [Apio2009]CONVENTION会议中心 贪心 set的更多相关文章

  1. bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心

    [Apio2009]CONVENTION会议中心 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1130  Solved: 444[Submit][S ...

  2. BZOJ1178 [Apio2009]CONVENTION会议中心

    本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description Siruseri政府建造了 ...

  3. 【BZOJ-1178】CONVENTION会议中心 倍增 + set (神思路好题!)

    1178: [Apio2009]CONVENTION会议中心 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 812  Solved: 323[Subm ...

  4. 1178: [Apio2009]CONVENTION会议中心

    1178: [Apio2009]CONVENTION会议中心 https://lydsy.com/JudgeOnline/problem.php?id=1178 分析: set+倍增. 首先把所有有包 ...

  5. 【bzoj1178】 Apio2009—CONVENTION会议中心

    http://www.lydsy.com/JudgeOnline/problem.php?id=1178 (题目链接) 题意 给出n个区间,问在区间两两不相交的情况下最多能选出多少区间,并输出字典序最 ...

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

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

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

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

  8. 【BZOJ】【1178】【APIO2009】convention会议中心

    贪心 如果不考虑字典序的话,直接按右端点排序,能选就选,就可以算出ans…… 但是要算一个字典序最小的解就比较蛋疼了= = Orz了zyf的题解 就是按字典序从小到大依次枚举,在不改变答案的情况下,能 ...

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

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

随机推荐

  1. 无线DOS攻击

    1.无线连接状态 IEEE 802.11定义了一种客户端状态机制,用于跟踪工作站身份验证和关联状态.无线客户端和AP基于IEEE标准实现这种状态机制.成功关联的客户站停留在状态3,才能进行无线通信.处 ...

  2. Elaticsearch 集群

    elasticsearch开源的搜索引擎:  ElasticSearch 个基于Lucene的搜索服务器:可以使用多节点的备份:集群设置: (类似是个数据库型.有索引有什么的).(lucene apa ...

  3. JavaScript之Dom1|DOM2|DOM3之DOM1【节点层次】

    长文慎读. 导航: 1.节点层次 2.Node类型 3.Document类型 4.Element类型 5.Text类型 6.Comment类型 7.CDATASection类型 8.DocumentT ...

  4. [SDOI2010]古代猪文 (欧拉,卢卡斯,中国剩余)

    [SDOI2010]古代猪文 \(solution:\) 这道题感觉综合性极强,用到了许多数论中的知识: 质因子,约数,组合数 欧拉定理 卢卡斯定理 中国剩余定理 首先我们读题,发现题目需要我们枚举k ...

  5. saltstack系列~第四篇

    简介 针对mysql的sls编写0 软件包推送部分  tool_rsync:     file.recurse:        - source: salt://files/mysql        ...

  6. 上传程序Dictionary 字典 哈希--多读一写锁ReaderWriterLock

    //上传程序Dictionary 字典 哈希 /// <summary> /// 车辆控制信息哈斯表,Key是终端号,Value是车辆信息控制对象 /// </summary> ...

  7. 消息队列介绍和SpringBoot2.x整合RockketMQ、ActiveMQ 9节课

    1.JMS介绍和使用场景及基础编程模型     简介:讲解什么是小写队列,JMS的基础知识和使用场景     1.什么是JMS: Java消息服务(Java Message Service),Java ...

  8. 基于URL的权限管理(三)

    思路:先创建一个专门的类ActiveUser用于存储用户登录的信息,主要用于存储用户id,账户,名称,菜单,权限. 认证拦截器主要是查看用户是否已登陆,如果没有转发到登陆界面,用户用账户跟密码登录时候 ...

  9. 解决Centos下yum无法更新

    问题: http://mirrors.cloud.aliyuncs.com/epel/6/x86_64/repodata/repomd.xml: [Errno 14] PYCURL ERROR 6 - ...

  10. 【转】Python之文件读写

    [转]Python之文件读写 本节内容: I/O操作概述 文件读写实现原理与操作步骤 文件打开模式 Python文件操作步骤示例 Python文件读取相关方法 文件读写与字符编码 一.I/O操作概述 ...