给一棵树,每次每次询问一个点是否是另一个点的祖先?
输入时是每个下标对应节点的儿子的数量
用dfs序 时间戳。。
如果一个点是另一个点的祖先,那么它的两个标记一定在祖先的范围之内
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(a, n) for(int i=a; i<=n; i++)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = , INF = 0x7fffffff;
int r[maxn], l[maxn], sum[], zstack[maxn];
bool vis[maxn];
int dfs_clock, top, k, n, m, x, y;
void dfs()
{
mem(vis, );
dfs_clock = zstack[top=] = ;
while(top > )
{
k = zstack[top]; //stack里存了结点 赋值给k后 k及对应了输入时的下标 即如果k<n 可以判定是否在输入的时候说了它有几个儿子
if(!vis[k])
{
vis[k] = , l[k] = ++dfs_clock;
if(k < n)
for(int i=k==?:sum[k-]+; i<=sum[k]; i++) zstack[++top] = i;
}
else
r[k] = ++dfs_clock, top--;
}
} int main()
{
int T, kase = ;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i=; i<n; i++)
{
int tmp;
scanf("%d", &tmp);
sum[i]=i==?tmp:sum[i-] + tmp; //每个下标对应的前缀和 即为当前节点的最后一个儿子的值
}
dfs();
printf("Case %d:\n", ++kase);
scanf("%d",&m);
while (m--){
scanf("%d%d",&x,&y);
if (l[x]<l[y] && r[x]>r[y]) puts("Yes");
else puts("No");
}
if(T) cout<<endl;
}
return ;
}