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. Android 应用程序集成FaceBook 登录及二次封装

    1.首先在Facebook 开发者平台注册一个账号 https://developers.facebook.com/ 开发者后台  https://developers.facebook.com/ap ...

  2. python之(re)正则表达式上

    python正则表达式知识预备 正则表达式使用反斜杠" \ "来代表特殊形式或用作转义字符,这里跟Python的语法冲突,因此,Python用" \\\\ "表 ...

  3. php CGI、Fastcgi、PHP-FPM的详细介绍与之间的关系

    以下PHP CGI.Fastcgi.PHP-FPM的一些信息归纳和汇总----->详细介绍与之间的关系 一:CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的 web ...

  4. Unity贴图锯齿

    之前在做一个Unity视频插件,发现渲染上去的贴图锯齿十分明显,开了抗锯齿也没用.最后在一次偶然的机会,发现了原来是贴图FilterMode设置有问题 之前用的是FilterMode.Point,后来 ...

  5. Android开发究竟用什么工具,Eclipse||AS

    所谓公欲善其事必先利器,那就让我们来看一下android的开发工具吧,安卓的开发工具有Eclipse和Android Studio,另外还有IntelliJ IDEA,可能很多人并不知道. 首先看一下 ...

  6. Python进阶【第一篇】socket

    1.socket模块 要使用socket.socket()函数来创建套接字.其语法如下: socket.socket(socket_family,socket_type,protocol=0) soc ...

  7. 【小白的CFD之旅】04 任务

    和老蓝见面之后的很长一段时间里,小白都没有接到任何老蓝的消息,再加上课比较多,小白也慢慢适应了白天上课,晚上窝在宿舍打游戏,偶尔也去图书馆看看书的生活,这样宁静的生活持续了差不多两个月.就在老蓝的影子 ...

  8. jquery选择器案例

    一.预期效果 实现一个效果,如下. 品牌列表默认精简显示,单击“显示全部品牌”按钮显示全部品牌,同时列表将推荐的品牌的名字高亮显示,按钮里的文字变成“精简显示品牌”.再次点击“精简显示品牌”回到初始页 ...

  9. 【原】iphone6来了,我该做点什么(兼容iphone6的方法)

    北京时间2014年9月10日凌晨1点,苹果公司正式发布其新一代产品 iPhone6,相信做webapp开发的同学对它是充满了好奇和等待,也担心它带来各种坑爹,高清的分辨率,升级的retina显示屏,我 ...

  10. UVA - 11584 Partitioning by Palindromes[序列DP]

    UVA - 11584 Partitioning by Palindromes We say a sequence of char- acters is a palindrome if it is t ...