[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 ...
随机推荐
- Android 使用EventBus进行Fragment和Activity通信
本文介绍EventBus的基本使用,以及用于Fragment和Activity之间通信. github地址: https://github.com/greenrobot/EventBus 版本是 Ev ...
- WindowsService+Quartz.NET快速搭建
新建一个Windows服务项目 nuget安装Quartz.NET,我这边使用的是2.3.3版本 1. Service改名 2. 添加安装程序,改名 3. ServiceInstaller->属 ...
- C/C++ 函数模板、全局变量、register、存储周期
1.函数声明时可以简写,如: int max(int,int): 2.函数模板: 格式: template <typename haha>或template <class haha& ...
- java将字段映射成另一个字段,关于 接口传参 字段不对应转换
在接口开发中我们经常会遇到一个问题,打个比方,我们的实体类A中有两个字段user和pwd但是接口中需要username和password这怎么办呢,我想到了两种方法:1.新创建一个实体类B或者new一 ...
- Oracle中的执行计划
使用autotrace sqlplus系统参数:SQL> set autotrace trace onSQL> select * from dual;DUM---XExecution Pl ...
- C# 實現文件壓縮-- 背景:服務器Log.txt 過多,佔用過多硬盤空間,壓縮備份后節省空間資源
1.壓縮實現代碼如下: 調用ICSharpCode.SharpZipLib.dll(free software,可以搜到源碼). 轉移指定目錄文件夾轉移到目標文件夾 壓縮目標文件夾 刪除目標文件夾 u ...
- Syslinux编译环境配置简要步骤
由于毕业设计要做一个加密U盘的LINUX,需要修改一sysylinux引导程序,在网上很少有关于syslinux编译环境配置的文章,在此简要总结一下,发出来共享. 需要的软件: 1. vmware ...
- git Please tell me who you are解决方法
在git创建项目时出现,是因为在创建git文件夹的时候信息不完善导致的下图是正确在git创建项目时出现,是因为在创建git文件夹的时候信息不完善导致的下图是正确1.git init2.git conf ...
- 二、spring中装配bean
在spring框架中提供了三种 bean的装配方式,当然这三种装配方式是可以灵活的进行组合使用的,项目中使用最多的是自动装配bean的方式,也就是通过注解的方式进行bean的装配,一下是四种装配方式的 ...
- 笔试算法题(37):二叉树的层序遍历 & 最长递增的数字串
出题:要求层序遍历二叉树,从上到下的层次,每一层访问顺序为从左到右,并将节点一次编号,输出如下:如果只要求打印指定的level的节点,应该如何实现. a b c d e f g h i 分 ...