祖孙询问(C++)

祖孙询问
难度级别:C; 运行时间限制:1000ms; 运行空间限制:256000KB; 代码长度限制:2000000B

试题描述

已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。


输入

输入第一行包括一个整数n表示节点个数。
接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。
第n+2行是一个整数m表示询问个数。
接下来m行,每行两个正整数x和y。 

输出

对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0。 

输入示例

10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19

输出示例

1
0
0
0

其他说明

数据范围:对于30%的数据,n,m≤1000,对于100%的.据,n,m≤40000,每个节点的编号都不超过40000。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int bin[16];
int n,m,root,cnt;
int q[40005],deep[40005],fa[40005][16];
bool vis[40005];
struct data{int to,next;}e[80005];int last[40005];
void insert(int u,int v)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;

}
void bfs()
{
int head=0,tail=1;
q[0]=root;vis[root]=1;
while(head!=tail)
{
int now=q[head];head++;
for(int i=1;i<=15;i++)
if(bin[i]<=deep[now])
fa[now][i]=fa[fa[now][i-1]][i-1];
else break;
for(int i=last[now];i;i=e[i].next)
if(!vis[e[i].to])
{
deep[e[i].to]=deep[now]+1;
fa[e[i].to][0]=now;
vis[e[i].to]=1;
q[tail++]=e[i].to;
}
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for(int i=0;i<=15;i++)
if(t&bin[i])x=fa[x][i];
for(int i=15;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if(x==y)return y;
return fa[x][0];
}
int main()
{
bin[0]=1;for(int i=1;i<=15;i++)bin[i]=bin[i-1]<<1;
n=read();
for(int i=1;i<=n;i++)
{
int u=read(),v=read();
if(v==-1)root=u;
else insert(u,v);
}
bfs();
m=read();
for(int i=1;i<=m;i++)
{
int a=read(),b=read(),t=lca(a,b);
if(a==t&&b!=t)puts("1");
else if(a!=t&&b==t)puts("2");
else puts("0");
}
return 0;
}

时间: 2024-08-05 18:22:19

祖孙询问(C++)的相关文章

祖孙询问

祖孙询问 描述 已知一颗有根树.有m个询问.每个询问给出了一对节点x,y,输出x,y的祖孙关系 輸入 第一行节点数目n接下来n行,每行一对整数a,b,表示a和b之间有边.如果b==-1,那么a就是数根接下来是一个整数m,表示询问的个数接下来m行,每行两个正整数x,y 輸出 对于每一个询问,如果x是y的祖先,输出1:如果y是x的祖先,输出2:否则输出0 輸入範例 1 10 234 -1 12 234 13 234 14 234 15 234 16 234 17 234 18 234 19 234

9.14noip模拟试题

中文题目名称 祖孙询问 比赛 数字 英文题目名称 tree mat num 可执行文件名 tree mat num 输入文件名 tree.in mat.in num.in 输出文件名 tree.out mat.out num.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 附加样例文件 有 有 有 题目类型 传统 传统 传统 二.              提交源程序文件名 对于pascal语言 tree.pas mat.pas num.

2014-10-5 NOIP模拟赛

祖孙询问 (tree.pas/c/cpp) [问题描述] 已知一棵n个节点的有根树.有m个询问.每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系. [输入格式] 输入第一行包括一个整数n表示节点个数. 接下来n行每行一对整数对a和b表示a和b之间有连边.如果b是-1,那么a就是树的根. 第n+2行是一个整数m表示询问个数. 接下来m行,每行两个正整数x和y. [输出格式] 对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0. [样例输入] 10 234 -1

NOIP练习赛题目3

魔兽争霸 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 小x正在销魂地玩魔兽他正控制着死亡骑士和n个食尸鬼(编号1-n)去打猎死亡骑士有个魔法,叫做“死亡缠绕”,可以给食尸鬼补充HP战斗过程中敌人会对食尸鬼实施攻击,食尸鬼的HP会减少,小x希望随时知道自己部队的情况,即HP值第k多的食尸鬼有多少HP,以便决定如何施放魔法.请同学们帮助他:)小x向你发出3种信号:(下划线在输入数据中表现为空格)A_i_a表示敌军向第i个食

【考试】9.18

最近这题解是真不想写, 正好这次不太难,就放个代码吧 1>比赛 新奇的方法,但是我不想分析 精度操作很烦人 #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int n; const int N=5e4+3; long long a[N],b[N]; long long sum[N],sq_sum[N],ans; int main() { scanf("

10.27--11.3 一周刷题记录

exgcd 贝祖定理推广 贝祖定理可以推广到n个,n>=2 ax+by+cz+...=k if(k%gcd(a,b,c,...)==0) 该式子有整数解 else 没有整数解 Forsaken喜欢数论 因为空间限制,直接省略掉sum数组 记得sum 开long long! int n; const int N=3e7+10; int v[N],p[N],tot_p; long long sum; inline void shai(){ rep(i,2,n){ if(v[i]==0){ v[i]=

算法提高课——图论

图论难点:问题的转化和抽象(可看成特殊的某一类DP) 图论与DP的联系: DP问题(从集合角度分析最优化问题)可以看成从F(0,0).F(0,1).F(1,2)......F(0,m)到F(n,m)的最长路.因此DP问题可以转化为拓扑图(一般DP问题的状态间无环)上的最短(长)路. 当DP依赖关系不具有拓扑序时(即存在环时),可以将其转化为最短路,也可以用高斯消元. //TLE的原因常常是没有memsert //st数组在不同算法中的用法: 单源最短路的建图方式 AcWing 1129. 热浪

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

luogu P2709 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3