欢迎访问~原文出处——博客园-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. Hibernate非主键一对多关联。

    Unit表 id,code User表 id,ucode ...@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="ucode" ...

  2. python技巧 列表推导

    val = [expression for value in collection if condition] 等价于 val = []for value in collection:    if c ...

  3. 运维数据库平台~inception审核规则详解

    ---恢复内容开始--- 一 简介:这次我们来介绍最核心的审核功能 二 讲解:简单来说 inception就是mysql的二次过滤,何谓二次过滤,我们知道,mysql本身都有自己的审核规则,为业界所通 ...

  4. Database学习 - mysql 数据库 事务操作

    事务 事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. 数据库开启事务命令: start transaction   开启事务 rollback  回滚事务,即撤销指定的 ...

  5. iOS性能优化技巧

    通过静态 Analyze 工具,以及运行时 Profile 工具分析性能瓶颈,并进行性能优化.结合本人在开发中遇到的问题,可以从以下几个方面进行性能优化. 一.view优化 1.不透明的View 设置 ...

  6. win10 + ubuntu双系统详细安装过程

    由于搞深度学习,电脑跟不上,换了一台神舟战神Z8,于是装一个ubuntu双系统,没想到几乎花了一天,还花了80个软妹币找人帮忙,蓝瘦,现在写下来供大家参考: 不得不说,win10 + ubuntu双系 ...

  7. 【转】使用SevenZipSharp压缩、解压文件

    引用 下载之后引用“SevenZipSharp.dll”至项目中,然后将“7z.dll”放到bin目录下,或者这样引用:SevenZipCompressor.SetLibraryPath(" ...

  8. zabbix3.0监控centos当主机cpu使用率超过90%的时候报警

    在windows系统中监控cpu利用率非常容易,自带模板就有这样的功能,但是在linux里面没有默认的模板 只有cpu的负载,默认当cpu的负载在一定时间内5以上报警 cpu utilization中 ...

  9. nagios系列(八)之nagios通过nsclient监控windows主机

    nagios通过nsclient监控windows主机 1.下载NSClient -0.3.8-Win32.rar安装在需要被监控的windows主机中 可以设置密码,此处密码留空 2.通过在nagi ...

  10. mongodb数据库安装及常见操作

    客户端和服务端的安装 # rpm -ivh mongo-10gen-2.4.6-mongodb_1.x86_64.rpm mongo-10gen-server-2.4.6-mongodb_1.x86_ ...