[bzoj3910]火车_并查集_倍增LCA
火车 bzoj-3910
题目大意:给定一棵n个节点的树,你需要顺次经过m个互不相同的节点,如果一个节点在之前的路径上被经过过,它不必再被特意经过。问走过的路径长度。
注释:$1\le n\le 5\cdot 10^5$,$1\le m\le 4\cdot 10^5$。
想法:
考场上切了/xyx
考虑暴力:顺次枚举所有必经点然后暴力爬,标记为经过过即可,总时间复杂度为O(nm)。
我们发现如果两个点之间的一些路径是vis那么他们没有必要被在此枚举一遍。
所以如果一个节点被到达过我们将它的并查集内的Father连向它树上的父亲,表示这个节点已经被删去了。
再次遍历的时候我们爬并查集就行了。
更新答案的话我们用倍增求出两点的LCA,用dep值计算路径长度累加答案即可。
显然每个点只会被删除一次,而且只会被遍历一次因为遍历之后就会被删掉。
故总时间复杂度为O(n+m)。
最后,附上丑陋的代码... ...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
using namespace std;
typedef long long ll;
int to[N<<1],nxt[N<<1],head[N],tot;
int dep[N],f[25][N],F[N];
bool vis[N]; int go[N];
inline void add(int x,int y) {to[++tot]=y; nxt[tot]=head[x]; head[x]=tot;}
int find(int x) {return F[x]==x?x:F[x]=find(F[x]);}
void dfs(int pos,int fa)
{
// puts("Fuck");
dep[pos]=dep[fa]+1; f[0][pos]=fa; for(int i=1;i<=23;i++) f[i][pos]=f[i-1][f[i-1][pos]];
for(int i=head[pos];i;i=nxt[i]) if(to[i]!=fa) dfs(to[i],pos);
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=23;~i;i--) if(dep[f[i][x]]>=dep[y]) x=f[i][x];
if(x==y) return x;
for(int i=23;~i;i--) if(f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y];
return f[0][x];
}
inline void update(int x)
{
vis[x]=true; for(int i=head[x];i;i=nxt[i]) if(to[i]!=f[0][x]) F[to[i]]=x;
}
void Lca(int x,int y)
{
// puts("Fuck");
int z=lca(x,y);
while(dep[x]>dep[z])
{
update(x); x=f[0][find(x)];
}
// printf("Fuck %d\n",y);
while(dep[y]>dep[z])
{
// printf("Fuck %d\n",y);
update(y);
// printf("Shit %d\n",z);
y=f[0][find(y)];
// printf("Shit %d\n",z);
}
update(z);
// puts("Fuck");
}
int main()
{
// freopen("airline.in","r",stdin);
// freopen("airline.out","w",stdout);
int x,y; ll ans=0;
int n,m,a; scanf("%d%d%d",&n,&m,&a); int pre=a; for(int i=1;i<n;i++) {scanf("%d%d",&x,&y); add(x,y); add(y,x);}
for(int i=1;i<=n;i++) F[i]=i;
dfs(1,1);
// printf("%d %d %d\n",lca(1,2),lca(2,3),lca(3,4));
for(int i=1;i<=m;i++) scanf("%d",&go[i]); for(int i=1;i<=m;i++)
{
if(!vis[go[i]])
{
// printf("%d\n",go[i]);
ans+=dep[pre]+dep[go[i]]-dep[lca(pre,go[i])]*2;
// printf("%d %d %d %d %d %d\n",pre,go[i],lca(pre,go[i]),dep[pre],dep[go[i]],dep[lca(pre,go[i])]);
Lca(pre,go[i]);
pre=go[i];
}
}
printf("%lld\n",ans);
return 0;
}
小结:比较有趣的一道题。
[bzoj3910]火车_并查集_倍增LCA的更多相关文章
- poj1182食物链_并查集_挑战程序设计竞赛例题
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 65534 Accepted: 19321 Description ...
- BZOJ_3362_[Usaco2004 Feb]Navigation Nightmare 导航噩梦_并查集
BZOJ_3362_[Usaco2004 Feb]Navigation Nightmare 导航噩梦_并查集 Description 农夫约翰有N(2≤N≤40000)个农场,标号1到N,M( ...
- BZOJ_2303_[Apio2011]方格染色 _并查集
BZOJ_2303_[Apio2011]方格染色 _并查集 Description Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好, ...
- BZOJ_1015_[JSOI2008]星球大战_并查集
BZOJ_1015_[JSOI2008]星球大战_并查集 题意:很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的 机遇,一支反抗军摧毁了帝国的超级武器, ...
- BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换
BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换 Description 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置 ...
- BZOJ_2443_[Usaco2011 Open]奇数度数 _并查集+树形DP
BZOJ_2443_[Usaco2011 Open]奇数度数 _并查集. Description 奶牛们遭到了进攻!在他们的共和国里,有N(1 <= N <=50,000)个城市,由M(1 ...
- 【BZOJ4569】萌萌哒(并查集,倍增)
[BZOJ4569]萌萌哒(并查集,倍增) 题面 BZOJ 题意: 有一个长度为\(n\)的数 给定\(m\)个限制条件 每次限制\(l1-r1\)与\(l2-r2\)是相同的 求出方案数 题解 如果 ...
- [Comet OJ - Contest #6 D][48D 2280]另一道树题_并查集
另一道树题 题目大意: 数据范围: 题解: 这个题第一眼能发现的是,我们的答案分成两种情况. 第一种是在非根节点汇合,第二种是在根节点汇合. 尝试枚举在第几回合结束,假设在第$i$回合结束的方案数为$ ...
- hdu 2473 Junk-Mail Filter(并查集_虚节点)2008 Asia Regional Hangzhou
感觉有些难的题,刚开始就想到了设立虚节点,但是实现总是出错,因为每次设立了虚节点之后,无法将原节点和虚节点分开,导致虚节点根本无意义. 以上纯属废话,可以忽略…… 题意—— 给定n个点(0, 1, 2 ...
随机推荐
- Spring注解驱动开发之声明式事务
前言:现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解.原理,比如@Conditional.@Import.@Ena ...
- 纯css实现的三级水平导航菜单
vscode练习使用开发纯css的三级水平导航菜单.先上图: 1.html5布局 <html> <head> <meta charset="UTF-8" ...
- Java集合框架源码(三)——arrayList
1. ArrayList概述: ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部 ...
- leetcode:single-number-ii(Java位运算)
题目 Given an array of integers, every element appears three times except for one. Find that single on ...
- qt5.8 链接mysql错误:driver not load
转载请注明出处:http://www.cnblogs.com/dachen408/p/7155858.html 问题:qt5.8 链接mysql错误:driver not load. 解决方案:1.安 ...
- 企业面试之LeetCode刷题心得
谈起刷LeetCode的心得,想要先扯点别的,说实话我是比较自虐的人,大学时候本专业从来不好好上,一直觊觎着别人的专业,因为自己文科生,总觉得没有项技术在身出门找工作都没有底气,然后看什么炫学什么,简 ...
- Discuz 页面不能加载插件的原因和解决方法
模板中,<!--{subtemplate common/headerF}-->这样就不能加载 source/class/class_template.php里65行附近代码 $header ...
- scrapy 的分页爬取 CrawlSpider
1.创建scrapy工程:scrapy startproject projectName 2.创建爬虫文件:scrapy genspider -t crawl spiderName www.xxx.c ...
- docker使用registry搭建本地私有仓库
参考链接来自:http://blog.csdn.net/wangtaoking1/article/details/44180901/ 和Mavan的管理一样,Dockers不仅提供了一个中央仓库,同时 ...
- RackTables在LNMP系统的安装及使用
RackTables是一款优秀的机房管理系统,可以十分方便的登记机房设备和连接情况,非常适合小型机房的运维.RackTables是PHP开发的免费系统,最新版本为0.20.14,PHP版本要求不低于P ...