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 学习 - 18.TextField 自定义菜单事件,复制和微信分享

    菜单事件包括,剪切.拷贝.全选.分享...,此 demo 只有 copy.share 1.定义 field 继承与 UITextField - (BOOL)canPerformAction:(SEL) ...

  2. ORA-39242 错误

    转载: Oracle 11g Release 1 (11.1) Data Pump 技术 http://docs.oracle.com/cd/B28359_01/server.111/b28319/d ...

  3. JVM之Parallel Old收集器

    Parallel Scavenge的老年代版本 标记-整理算法 注重吞吐量及cpu资源敏感环境.

  4. mybatis 配置返回集合collection时只有一条记录

    查询语句配置如下: <select id="selectCustomerList" resultMap="CustomerDtoMap" paramete ...

  5. docker-9 supervisord 参考docker从入门到实战

    参考docker从入门到实战 使用 Supervisor 来管理进程 Docker 容器在启动的时候开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务.但我们经常需要在一个机 ...

  6. MariaDB的GTID复制和多源复制

    什么是GTID? GTID就是全局事务ID(global transaction identifier ),最初由google实现,官方MySQL在5.6才加入该功能.GTID实际上是由UUID+TI ...

  7. windows下OpenSSL加密证书安装步骤与使用方法

    OpenSSL加密证书一般用于签名认证,含私钥和公钥.在Linux系统中,OpenSSL一般是已经安装好了,可以直接使用.而在Windows系统中,是需要安装使用的. 最近在使用支付平台时,用到了Op ...

  8. [WPF系列]-Adorner

      简介 通常我们想对现有的控件,做些修饰时我们就会想到一个装饰模式.WPF中也提供了这样的实现思路:通过将Adorner添加到AdornerLayer中来实现装饰现有控件的效果.如图示:   本来T ...

  9. ik扩展支持Solr配置

    扩展ik原生代码:public class IKAnalyzerTokenizerFactory extends TokenizerFactory{ private boolean useSmart; ...

  10. MySQL命令行下执行.sql脚本详解

    本文主要介绍一个在MySQL命令行下执行脚本文件的例子,通过这个例子让我们来了解一下在命令行下MySQL是怎样执行脚本的吧.现在我们开始介绍这一过程. 1.首先编写sql脚本,保存为的:book.sq ...