欢迎访问~原文出处——博客园-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. DEV Winform分页用户组件

    资源部分在QQ群:616945527基于服务端数据分页,你也可以修改成本地分页.调用方法添加用户控件到窗体 public int curPage = 1;public int pageSize = 1 ...

  2. 二、Internet地址结构

    IP路由器实现的转发程序使用IP地址来识别流量去向.IP地址也表示流量来源. 2.1 IP地址的表示 IPV4地址通常采用点分四组或点分十进制表示法,如192.168.1.1. 点分四组表示法由四个用 ...

  3. .NET 单点登录开源项目

    1. https://www.apereo.org/cas/client-integration 2.源码下载 https://wiki.jasig.org/display/CASC/.Net+Cas ...

  4. Ribbon实现Office开始菜单

    Ribbon实现Office开始菜单 界面效果: 首先:在主窗体上拖入popupMenu控件和imageCollection控件 然后选中popupMenu点击三角,再点击Run Designer在弹 ...

  5. rest framework错误笔记——AssertionError: Cannot apply DjangoModelPermissionsOrAnonReadOnly on a view that does not set `.queryset` or have a `.get_queryset()` method.

    用到@api_view装饰器时,访问路由查看api数据时,报错: AssertionError: Cannot apply DjangoModelPermissionsOrAnonReadOnly o ...

  6. 自定义滤镜 ColorMatrixFilter

    var url:URLRequest = new URLRequest("Koala.jpg"); var l:Loader = new Loader(); l.contentLo ...

  7. POJ3304 Segments 【线段直线相交】

    题意: 给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!. 思路: 计算几何.这道题要思考到两点: 1:把问题转化为是否存在一条直线 ...

  8. 你真的懂 ajax 吗?

    前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库: ...

  9. 一篇不错的CUDA入门

    鉴于自己的毕设需要使用GPU CUDA这项技术,想找一本入门的教材,选择了Jason Sanders等所著的书<CUDA By Example an Introduction to Genera ...

  10. 解决git: 'subtree' is not a git command. See 'git --help'.

    一.第一方法 git clone https://github.com/git/git.git cd git/contrib/subtree sudo make prefix=/usr sudo ma ...