4082: [Wf2014]Surveillance

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 260  Solved: 100
[Submit][Status][Discuss]

Description

给你一个长度为len的环,以及n个区间,要你选择尽量少的区间,使得它们完全覆盖整个环。问最少要多少个区间。

Input

输入数据的第一行是两个整数len和n,代表环的长度以及区间个数。之后n行描述的是n个区间,每个区间分别用一对数字(a,b)表示,若a≤b则表示这个区间覆盖的是[a,b]部分,否则表示这个区间覆盖的是除掉[a+1,b-1]以外的其他部分。

Output

输出只有一行,一个整数,代表覆盖整个环所需要的最少区间个数。

Sample Input

100 7
1 50
50 70
70 90
90 40
20 60
60 80
80 20

Sample Output

3

HINT

Source

鸣谢qpswwww提供译文

Solution

这个题还是很巧妙的啊!

首先这个题有个序列上的版本在CodeVS,那样只需要贪心的排序,然后从头开始每次选一个覆盖最长的即可。

但是环上的情况显然不能这么搞,因为可以从每个点开始搞,都会有不同的方法。

但是这个思路还是可以利用的,我们展环成链,还是贪心的按照右端从小到大排序。

序列上的版本,我们是直接从起始节点开始每次都选一个覆盖最长的,那这里同样,只有全部是覆盖最长的才有可能是最优的。

那么我们对每个节点向它覆盖最长的连边,这样会形成一棵树,可以发现,这样树上两点的距离就是答案。

所以我们求一下LCA,枚举一下每个点做起始时的答案,取一下min即可。

还是有很多细节需要处理的,比如我们很有可能会覆盖过多,所以最后并不是每次查$i->i+L$,所以我们需要一开始用一个set维护一下这个东西。

这样总的复杂度大概是$O(NlogN)$,范围大概是$10^{6}$的,有点虚所以写的链剖

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
#define INF 0x7fffffff
inline int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') {ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x;
}
#define MAXN 1000010
struct SecNode
{
int s,t;
bool operator < (const SecNode & A) const {return t==A.t? s<A.s:t<A.t;}
}sec[MAXN];
struct EdgeNode{int next,to;}edge[MAXN<<];
int head[MAXN<<],cnt=;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int size[MAXN<<],fa[MAXN<<],deep[MAXN<<],son[MAXN<<],top[MAXN<<];
bool ok[MAXN<<];
int N,L,ans=INF;
set<int>st;
inline void DFS_1(int now)
{
if (deep[now]) return;
if (!fa[now])
{
deep[now]=;
if (now>L && ok[now]) fa[now]=*L+,InsertEdge(fa[now],now);
return;
}
DFS_1(fa[now]);
InsertEdge(fa[now],now);
deep[now]=deep[fa[now]]+;
}
inline void DFS_2(int now)
{
size[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now])
{
DFS_2(edge[i].to);
size[now]+=size[edge[i].to];
if (size[son[now]]<size[edge[i].to]) son[now]=edge[i].to;
}
}
inline void DFS_3(int now,int chain)
{
top[now]=chain;
if (son[now]) DFS_3(son[now],chain);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=son[now] && edge[i].to!=fa[now])
DFS_3(edge[i].to,edge[i].to);
}
inline int LCA(int u,int v)
{
v=*st.lower_bound(v);
if (!top[u] || !top[v]) return -;
while (top[u]!=top[v])
{
if (deep[top[u]]<deep[top[v]]) swap(u,v);
u=fa[top[u]];
}
if (deep[u]>deep[v]) swap(u,v);
return u;
} int main()
{
L=read(),N=read();
for (int i=; i<=N; i++) sec[i].s=read(),sec[i].t=read(),sec[i].t=sec[i].t<sec[i].s? sec[i].t+L:sec[i].t;
sort(sec+,sec+N+);
for (int i=N; i; i--)
if (!fa[sec[i].s])
for (int j=sec[i].s; j<=L && j<=sec[i].t && !fa[j]; j++)
{ok[ fa[j]=sec[i].t+ ]=; if (fa[j]>L) st.insert(fa[j]);}
st.insert(*L+);
for (int i=; i<=L*; i++) DFS_1(i);
DFS_2(*L+); DFS_3(*L+,*L+);
for (int lca,i=; i<=L; i++) lca=LCA(i,i+L),ans=lca!=-? min(ans,deep[i]-deep[lca]):ans;
if (ans==INF) puts("impossible"); else printf("%d\n",ans);
return ;
}

【BZOJ-4082】Surveillance 树链剖分 LCA + 贪心的更多相关文章

  1. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  2. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  3. 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)

    题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...

  4. 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心

    Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...

  5. BZOJ 3083 遥远的国度 树链剖分

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 797  Solved: 181[Submit][Status] Descrip ...

  6. CodeForces 916E Jamie and Tree(树链剖分+LCA)

    To your surprise, Jamie is the final boss! Ehehehe. Jamie has given you a tree with n vertices, numb ...

  7. NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分

    原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...

  8. Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心

    传送门 题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值.需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的 ...

  9. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

随机推荐

  1. iOS开发之巧用Block和代理方法结合来传值

    好久没写技术博客了,因为996的工作周期已经持续好几个月了.每天晚上回家都没有太多精力学习很多其他的东西,而且很多时候是接着完善工作的项目的模块开发.所以博客停歇了这么久,更新率也低了不少,今天补充一 ...

  2. [css]我要用css画幅画(五)

    接着之前的[css]我要用css画幅画(四), 这次我给小明和静静增加了对话,用了简单的动画效果. github:https://github.com/bee0060/Css-Paint , 完整代码 ...

  3. js实现动态操作table

     本章案例为通过js,动态操作table,实现在单页面进行增删改查的操作. 简要案例如下: <%@ page language="java" contentType=&quo ...

  4. [转]看懂UML类图

    这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图所表达的含义和最终的代码 ...

  5. Guest Speaker on 2015 WinHEC Shenzhen 秋季大会

    继今年3月份的WinHEC春季大会,秋季大会于11月10日-11日深圳如期举行.此次大会的主题是Windows 10 IoT和Microsoft Azure,云和端的无缝连接是微软物联网解决方案的典型 ...

  6. Linux LVM学习总结——删除卷组VG

    在Linux系统中,如何删除一个卷组(VG)呢? 下面我总结了一下如何删除卷组(VG)的具体步骤,仅供参考,如有不足,敬请指出.谢谢!在下面的例子中,我想删除卷组VolGroup05. 步骤1: 查看 ...

  7. Windows Server 2012 虚拟化实战:存储(一)

    在计算机世界我们随处可以见的一种方法,那就是抽象.1946年冯诺依曼提出了计算机的基本结构包含:计算器,存储器和I/O设备.这可能是对计算机这一新生事物最重要的一次抽象,它直接影响了今后几十年计算机软 ...

  8. Linux – Usermod命令参数解析和实例说明

    usermod 命令修改系统帐户文件来反映通过命令行指定的变化 1. 首先看看usermod都是有哪些参数 [root@hxweb101 ~]$ usermod --help Usage: userm ...

  9. 利用mysql-proxy进行mysql数据库的读写分离

    实验系统:CentOS 6.6_x86_64 实验前提:防火墙和selinux都关闭 实验说明:本实验共有4台主机,IP分配如拓扑 实验软件:mariadb-10.0.20 mysql-proxy-0 ...

  10. delphi WebBrowser控件上网页验证码图片识别教程(一)

    步骤一:获取网页中验证码图片的url地址 在delphi中加入一个BitBtn和一个memo以及WebBrowser控件实现网页中验证码图片的url地址的获取 程序如下:procedure TForm ...