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. Ruby的require相关知识

    1. 在调用require xxx之前,需要确定xxx这个gem已经安装过了(使用gem install xxx,安装位置可以使用gem env列出),或者xxx是Ruby内置的标准函数库(StdLi ...

  2. Ignite安装配置——中篇

    Linux Ignite配置——上篇大体介绍了一下Ignite工具的功能.特性等,以及如何在Linux 上安装配置.从上篇可见Ignite安装非常的简单方便.下面介绍一下Ignite Reposito ...

  3. 使用TortoiseGit 来进行日常操作

    TortoiseSVN大家应该都很熟悉,相应的,git也有一个工具是TortoiseGit. 下载地址: http://download.tortoisegit.org/tgit/previews/ ...

  4. TCP首部解析

    TCP首部: TCP数据被封装在一个IP数据报中,如下: TCP首部数据格式: 16位源都口号,16为目的端口号用于寻找发送端和接收端的应用进程,加上IP首部的源端IP及终端IP,唯一的确认一个TCP ...

  5. PHP的错误机制总结

    PHP的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课. 特别说明:文章的PHP版本使用5.5.32 PHP的错误级别 首先需要了解php有哪些错误.截至到php5.5,一 ...

  6. [Java入门笔记] 面向对象编程基础(二):方法详解

    什么是方法? 简介 在上一篇的blog中,我们知道了方法是类中的一个组成部分,是类或对象的行为特征的抽象. 无论是从语法和功能上来看,方法都有点类似与函数.但是,方法与传统的函数还是有着不同之处: 在 ...

  7. x01.Weiqi.11: 神来之笔

    在围棋中,一子两用,可谓妙手,而一子三用,则可称之为神来之笔.在解决征子问题时,一不小心,也来了个神来之笔,其代码如下: // 征子判断,p1, p2 为气,p2 为前进方向,p 为逃跑之子. boo ...

  8. linux安装VirualBox虚拟机

    第一步:安装VNC 1. 安装vnc yum install -y tigervnc* 2.启动vncserver [root@xxx ~]# vncserver You will require a ...

  9. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

  10. 简单的词法分析和语法分析(C++实现,CodeBlocks+GCC编译)

    说明: 分析的语言是SNL语言,详见<编译程序的设计与实现>( 刘磊.金英.张晶.张荷花.单郸编著) 词法分析就是实现了词法分析的自动机 语法分析使用递归下降法 运行结果: 词法分析 得到 ...