[CF983E]NN country
题意:给一棵树,有许多条巴士线路$(a_i,b_i)$(巴士在路径上每个点都会停车),多次询问从一点到另一点最少要坐多少次巴士
首先dfs一遍预处理出一个点向上坐$2^k$次巴士能到的最浅点,于是我们能很快地查询一个点往上走到另一个点最少要坐多少次巴士
对于询问$(u,v)$,我们肯定是贪心地坐车,每次坐尽可能远,路径是$u\rightarrow lca_{u,v}\rightarrow v$,我们找到$l_u$表示从$u$开始坐$a$次巴士能到的最浅点,并且再坐一次巴士就能到$lca_{u,v}$,同理坐$b$次巴士到$l_v$
那么如果有线路覆盖$(l_u,l_v)$,那么答案就是$a+b+1$,否则答案是$a+b+2$
考虑离线处理路径覆盖问题,一次dfs即可解决:假设当前节点是某个询问的$l_u$,我们先查询$l_v$的子树和并记下来,然后将所有从$l_u$开始的巴士路线的终点权值$+1$,递归进儿子,最后再查询一次$l_v$的子树和,如果它和之前查询过的值不同,那么说明有巴士线路覆盖$(l_u,l_v)$,否则没有,这个过程用树状数组维护dfs序即可
我写得又慢又丑qwq真实滥用STL
upd:这可能就是dsu on tree?
#include<stdio.h>
#include<vector>
using namespace std;
int h[200010],nex[200010],to[200010],in[200010],ou[200010],dep[200010],fa[200010][18],up[200010][18],M;
void add(int a,int b){
M++;
to[M]=b;
nex[M]=h[a];
h[a]=M;
}
void dfs(int x){
M++;
in[x]=M;
dep[x]=dep[fa[x][0]]+1;
for(int i=h[x];i;i=nex[i])dfs(to[i]);
ou[x]=M;
}
int lca(int x,int y){
int i;
if(dep[x]<dep[y])swap(x,y);
for(i=17;i>=0;i--){
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
}
if(x==y)return x;
for(i=17;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
struct pr{
int x,y;
pr(int a=0,int b=0){x=a;y=b;}
};
vector<pr>bg[200010];
void merge(int&x,int y){
if(x==0||y==0)
x|=y;
else if(dep[y]<dep[x])x=y;
}
void dfs2(int x){
for(pr t:bg[x])merge(up[x][0],t.y);
for(int i=h[x];i;i=nex[i]){
dfs2(to[i]);
merge(up[x][0],up[to[i]][0]);
}
if(up[x][0]==x)up[x][0]=0;
}
pr bus(int x,int y){
pr t;
int i;
for(i=17;i>=0;i--){
if(dep[up[x][i]]>dep[y]){
x=up[x][i];
t.y|=1<<i;
}
}
t.x=x;
return t;
}
int ans[200010],s[200010],n;
vector<pr>ques[200010];
int lowbit(int x){return x&-x;}
int query(int x){
int res=0;
while(x){
res+=s[x];
x-=lowbit(x);
}
return res;
}
int query(int l,int r){
return query(r)-query(l-1);
}
void modify(int x){
while(x<=n){
s[x]++;
x+=lowbit(x);
}
}
void dfs3(int x){
vector<int>v;
vector<int>::iterator it;
for(pr t:ques[x])v.push_back(query(in[t.x],ou[t.x]));
for(pr t:bg[x])modify(in[t.x]);
for(int i=h[x];i;i=nex[i])dfs3(to[i]);
it=v.begin();
for(pr t:ques[x]){
if(*it==query(in[t.x],ou[t.x]))ans[t.y]++;
it++;
}
}
int main(){
int m,q,i,j,x,y;
pr tx,ty;
scanf("%d",&n);
for(i=2;i<=n;i++){
scanf("%d",fa[i]);
add(fa[i][0],i);
}
M=0;
dfs(1);
for(j=1;j<18;j++){
for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];
}
scanf("%d",&m);
while(m--){
scanf("%d%d",&x,&y);
j=lca(x,y);
bg[x].push_back(pr(y,j));
bg[y].push_back(pr(x,j));
}
dfs2(1);
for(j=1;j<18;j++){
for(i=1;i<=n;i++)up[i][j]=up[up[i][j-1]][j-1];
}
scanf("%d",&q);
for(i=1;i<=q;i++){
scanf("%d%d",&x,&y);
j=lca(x,y);
tx=bus(x,j);
ty=bus(y,j);
if(x==j){
if(up[ty.x][0]==0)
ans[i]=-1;
else
ans[i]=ty.y+1;
}else if(y==j){
if(up[tx.x][0]==0)
ans[i]=-1;
else
ans[i]=tx.y+1;
}else{
if(up[tx.x][0]==0||up[ty.x][0]==0)
ans[i]=-1;
else{
ans[i]=tx.y+ty.y+1;
ques[tx.x].push_back(pr(ty.x,i));
}
}
}
dfs3(1);
for(i=1;i<=q;i++)printf("%d\n",ans[i]);
}
[CF983E]NN country的更多相关文章
- cf983E NN Country (倍增+dfs序+树状数组)
首先可以求出从某点做$2^k$次车能到的最浅的点,这个只要dfs一下,把它的孩子能到的最浅的点更新过来就可以 然后倍增地往上跳,不能跳到lca的上面,记录坐车的次数ans 此时有三种情况(设最远能跳到 ...
- CF983E NN country(倍增,差分)
题意 给定一棵树和若干条路线,每条路线相当于树上 x,y 之间的路径,途径路径上的每个点 给出若干个询问,每次询问从 u 到 v 至少需要利用几条路线 N,M,Q≤200000 题解 构建倍增数组g[ ...
- 【codeforces 983E】NN country
Description In the NN country, there are n cities, numbered from 1 to n, and n−1 roads, connecting t ...
- 【CodeForces】983 E. NN country 树上倍增+二维数点
[题目]E. NN country [题意]给定n个点的树和m条链,q次询问一条链(a,b)最少被多少条给定的链覆盖.\(n,m,q \leq 2*10^5\). [算法]树上倍增+二维数点(树状数组 ...
- Codeforces983E. NN country
新鲜出炉! $n \leq 200000$的树,给$m \leq 200000$条链,$q \leq 200000$个询问,每次问一条询问链最少用m条中的几条给定链覆盖其所有边,可能无解. 首先确定一 ...
- Codeforces 983E - NN country(贪心+倍增优化)
Codeforces 题面传送门 & 洛谷题面传送门 一道(绝对)偏简单的 D1E,但是我怕自己过若干年(大雾)忘了自己的解法了,所以过来水篇题解( 首先考虑怎么暴力地解决这个问题,不难发现我 ...
- 多校联训 DS 专题
CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...
- Codeforces Round #483 (Div. 1) 简要题解
来自FallDream的博客,未经允许,请勿转载,谢谢. 为了证明一下我又来更新了,写一篇简要的题解吧. 这场比赛好像有点神奇,E题莫名是道原题,导致有很多选手直接过掉了(Claris 表演24s过题 ...
- Abandoned country
Abandoned country Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
随机推荐
- 一些比较高效的CSS写法建议
当浏览器解析html的时候,它构造了一个文档树来展现所有被显示的元素. 它在特定的样式表中去匹配元素,根据标准的css的层叠,继承和顺序规则, 在mozilla的实现中(可能其他的也是这样),对于每一 ...
- [模拟赛] StopAllSounds
Description 小松鼠开心地在树之间跳跃着,突然她停了下来.因为眼前出现了一个 拿着专克超萌小松鼠的法宝----超萌游戏机的游客! 超萌游戏机之所以拥有这个名字,是因为它的屏幕是一个n × 2 ...
- codeforces 1065D
题目链接:https://codeforces.com/problemset/problem/1065/D 题意:给你一个又1~n^2组成的n行n列的矩阵,你可以走日字型,直线,斜线,现在要求你从1走 ...
- STM32 启动代码 bootloader
什么是启动代码? 启动代码是系统上电或者复位后运行的第一段代码,是进入C 语言的main 函数之前需要执行的那段汇编代码.STM32的启动代码在startup_stm32f10x_hd.s 启 ...
- 【poj3294-不小于k个字符串中最长公共子串】后缀数组
1.注意每两个串之间的连接符要不一样. 2.分组的时候要注意最后一组啊!又漏了! 3.开数组要考虑连接符的数量.100010是不够的至少要101000. #include<cstdio> ...
- unity下的Line of Sight(LOS)的绘制
先说说什么是Linf of Sight.在很多RTS游戏中,单位与单位之间的视野关系经常会受到障碍物遮挡.Line of Sight指的就是两个物体之间是否没有障碍物遮挡. 比如在dota中,玩家的视 ...
- DotNETCore 学习笔记 宿主
Hosting -------------------------------------------------------------------------- Setting up a Host ...
- ubuntu 安装wxpython以及boa-constructor
直接参考 官方的安装文档. 学习python 的时候就 用 wxPython . 那个时候用的是windows 的版本. 现在 用 ubuntu 下开发了.没有搭建好环境. 其实就一句话: sudo ...
- Python阶段复习 - part 2 - Python序列/持久化
1. 把一个数字的list从小到大排序,然后写入文件,然后从文件中读取出来文件内容,然后反序,在追加到文件的下一行中 >>> import json >>> imp ...
- cuda yv12_to_rgb24
前言 项目需要将yv12转rgb24,由于基于x86平台,开始就没多想,直接用ipp加速实现了,后来在评估项目瓶颈的时候发现,1080p的视频每一帧转换居然要花8ms,刚好项目里有用到nvidia g ...