Description

In the NN country, there are n cities, numbered from 1 to n, and n−1 roads, connecting them. There is a roads path between any two cities.

There are m bidirectional bus routes between cities. Buses drive between two cities taking the shortest path with stops in every city they drive through. Travelling by bus, you can travel from any stop on the route to any other. You can travel between cities only by bus.

You are interested in q questions: is it possible to get from one city to another and what is the minimum number of buses you need to use for it?

Input

The first line contains a single integer n (2≤n≤2⋅105) — the number of cities.

The second line contains n−1 integers p2,p3,…,pn (1≤pi<i), where pi means that cities pi and i are connected by road.

The third line contains a single integer m (1≤m≤2⋅105) — the number of bus routes.

Each of the next m m lines contains 2 integers a and b (1≤a,b≤n, a≠b), meaning that there is a bus route between cities a and b. It is possible that there is more than one route between two cities.

The next line contains a single integer q (1≤q≤2⋅105) — the number of questions you are interested in.

Output

Print the answer for each question on a separate line. If there is no way to get from one city to another, print −1. Otherwise print the minimum number of buses you have to use.

题意:给定一棵 $n$ 个点的树, $m$ 条链, $q$ 个询问,每次询问 $a$ 到 $b$ 之间的路径最少可用几条给定链完全覆盖,无解输出 $-1$ 。

分析:

对于每一条 $a$ 与$b$ 间的路径,都可拆分为 $a$ 到 $lca$ 的路径和 $b$ 到 $lca$ 的路径

采用贪心策略, $low[x][i]$ 表示从 $x$ 点出发向上选择不超过 $2^i$ 条链可抵达的深度最浅的点。这时对于每一个询问可将询问的两个端点修改为利用贪心策略跳到的深度大于 $lca$ 且深度最小的节点,并记录下答案,这个过程可以用倍增完成。注意特判端点即 $lca$ 的情况。

然后出现两种情况。若修改后的两个端点出现在同一条给定链上,答案为原答案 $+1$ ,否则答案为原答案 $+2$ 。问题模型转换为,每次询问一个点对是否出现在同一条给定链上。记录下 $dfs$ 序,在深搜过程中利用树状数组统计即可。

时间复杂度 $O(nlogn)$ 。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int N=2e5+;
const int inf=0x3f3f3f3f;
int n,m,Q,cnt,val,x,y,ind;
int deep[N],in[N],out[N],last[N];
int first[N],ans[N],tr[N];
int fa[N][],low[N][];
bool ok[N];
vector<int> a[N],b[N];
struct edge{int to,next;}e[N];
struct chain{int x,y,t;}c[N],q[N];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void ins(int u,int v){e[++cnt]=(edge){v,first[u]};first[u]=cnt;}
void dfs(int x)
{
in[x]=++ind;
for(int i=;(<<i)<=deep[x];i++)
fa[x][i]=fa[fa[x][i-]][i-];
for(int i=first[x];i;i=e[i].next)
{
deep[e[i].to]=deep[x]+;
dfs(e[i].to);
}
out[x]=ind;
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int d=deep[x]-deep[y];
for(int i=;(<<i)<=d;i++)
if((<<i)&d)x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;i--)
if((<<i)<=deep[x]&&fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][];
}
void dfslow(int x)
{
for(int i=first[x];i;i=e[i].next)
{
int to=e[i].to;dfslow(to);
if(deep[low[to][]]<deep[low[x][]])
low[x][]=low[to][];
}
}
int find(int x,int t)
{
if(deep[low[x][]]>deep[t]){val=-inf;return -;}
if(x==t){val=-;return ;}
val=;
for(int i=;i>=;i--)
if(deep[low[x][i]]>deep[t])
x=low[x][i],val|=(<<i);
return x;
}
int lowbit(int x){return x&(-x);}
void add(int x,int v){for(;x<=n;x+=lowbit(x))tr[x]+=v;}
int query(int x){int ans=;for(;x;x-=lowbit(x))ans+=tr[x];return ans;}
void work(int x)
{
for(int sz=b[x].size(),i=;i<sz;i++)
{
int t=b[x][i];
last[t]=query(out[q[t].y])-query(in[q[t].y]-);
}
for(int sz=a[x].size(),i=;i<sz;i++)add(in[a[x][i]],);
for(int i=first[x];i;i=e[i].next)work(e[i].to);
for(int sz=b[x].size(),i=;i<sz;i++)
{
int t=b[x][i];
if(query(out[q[t].y])-query(in[q[t].y]-)!=last[t])ok[t]=true;
}
}
int main()
{
n=read();
for(int i=;i<=n;i++)
fa[i][]=read(),ins(fa[i][],i);
dfs();
for(int i=;i<=n;i++)low[i][]=i;
m=read();
for(int i=;i<=m;i++)
{
c[i].x=read();c[i].y=read();
c[i].t=lca(c[i].x,c[i].y);
if(deep[c[i].t]<deep[low[c[i].x][]])
low[c[i].x][]=c[i].t;
if(deep[c[i].t]<deep[low[c[i].y][]])
low[c[i].y][]=c[i].t;
a[c[i].x].push_back(c[i].y);
a[c[i].y].push_back(c[i].x);
}
dfslow();
for(int t=;t<=n;t++)
for(int i=;i<=;i++)
low[t][i]=low[low[t][i-]][i-];
Q=read();
for(int i=;i<=Q;i++)
{
q[i].x=read();q[i].y=read();
q[i].t=lca(q[i].x,q[i].y);
ans[i]=;
x=find(q[i].x,q[i].t);ans[i]+=val;
y=find(q[i].y,q[i].t);ans[i]+=val;
if(x>&&y>)
{
q[i].x=x;q[i].y=y;
b[x].push_back(i);
}
}
work();
for(int i=;i<=Q;i++)
if(ok[i])ans[i]--;
for(int i=;i<=Q;i++)
printf("%d\n",ans[i]<?-:ans[i]);
return ;
}

【codeforces 983E】NN country的更多相关文章

  1. 【codeforces 415D】Mashmokh and ACM(普通dp)

    [codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...

  2. 【codeforces 370C】Mittens

    [题目链接]:http://codeforces.com/problemset/problem/370/C [题意] 给你n个人,每个人都有一双相同颜色的手套; 然允许在所有人之间交换手套; (每个人 ...

  3. 【42.07%】【codeforces 558A】Lala Land and Apple Trees

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  4. 【codeforces 546E】Soldier and Traveling

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  5. 【codeforces 752F】Santa Clauses and a Soccer Championship

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  6. 【27.66%】【codeforces 592D】Super M

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  7. 【codeforces 761B】Dasha and friends

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  8. 【codeforces 762B】USB vs. PS/2

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  9. 【codeforces div3】【E. Cyclic Components】

    E. Cyclic Components time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

随机推荐

  1. 使用cocoaPods和遇到的问题以及解决办法

    上一篇说到cocoaPods的安装,本篇就来说说cocoaPods的使用和遇到一些问题的解决办法( ⊙ o ⊙ ) 一.cocoaPods的创建使用 1.cd进入所在的项目目录 2.创建Podfile ...

  2. 关于WCF服务在高并发情况下报目标积极拒绝的异常处理

    最近弄了个wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好好的活着.于是开始查原因. 一般来说目标积极拒绝(TCP 10061)的异常主要是 ...

  3. Python小游戏之猜数字

    最近师兄师姐毕业,各种酒席,酒席上最常玩的一个游戏就是猜数字,游戏规则如下: 出题人在手机上输入一个0-100之间的数字,其它人轮流猜这个数字,如果你不幸猜中则要罚酒一杯.每次猜数字,出题人都要缩小范 ...

  4. 一般处理文件.ashx中使用文件session遇到的问题

    在给其他网站提供接口的时候用ashx做的,在文件调用cs中的方法,方法中的Session报错:System.NullReferenceException: 未将对象引用设置到对象的实例. /// &l ...

  5. 洛谷P1519 穿越栅栏 Overfencing

    P1519 穿越栅栏 Overfencing 69通过 275提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交  讨论  题解 最新讨论 USACO是100分,洛谷是20分 为什么 ...

  6. CMake 入门实战 | HaHack

    CMake 入门实战 | HaHack undefined

  7. 《javascript dom编程艺术》笔记(二)——美术馆示例

    这几天把这本书看完了,里面大部分知识我已经会了,所以看得就略简单,好多地方都没有再去动手去做,我知道这样是不对的,以后补吧. 现在我要做的是把这本书的笔记完结掉,不然总觉得有啥事没有做. 这个版本不是 ...

  8. 这些屌炸天的创业者为何对投资人说NO

    曾有人说,世上的创业者只分为两种,一种是找到投资的,一种是没有找到的. 但其实还有第三种,就是那些拒绝了投资人的创业者. 他们摒弃了投资人抛来的橄榄枝,并非不差钱,不接受投资的原因大体出于两个方面,一 ...

  9. JavaScript之获取节点

    JavaScriopt DOM有三大节点:元素节点.属性节点.文本节点. 其中获取元素节点的三种主要方法有: 1.document.getElementById();此方法根据节点的唯一id值获取节点 ...

  10. HDU 4612 Warm up (边双连通分量+缩点+树的直径)

    <题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...