题目大意:
给你前n个点的儿子数量,所有点按照题目所给定的序号顺序排列,再给你m个询问,问你a与b有没有父子关系(爷孙关系,等)。
解题思路:
题中结点的个数最多可达到2000000个,数据量过大,需要预处理。此处使用了栈模拟DFS,记录了各点出栈入栈的时间戳。而后询问时只需要判断a比b先入栈后出栈,则有亲子关系。
AC代码:
#include <cstdio>
#include <stack>
#include <cstring>
#define MAX 20000005
using namespace std;
int in[MAX],out[MAX];
int child[MAX];
int check[MAX];
int C[MAX];
int n;
int ka;
void solve()
{
stack<int>s;
int clock=0;
int now=0;
in[now]=clock++;
s.push(now);
while(1){
if(s.empty()){
break;
}
if(now>=n){
out[now]=clock++;
s.pop();
if(s.empty()){
break;
}
now = s.top();
}
if(child[now]<check[now+1]){
int cur = child[now];
child[now]++;
s.push(cur);
in[cur]=clock++;
now=cur;
}
else{
s.pop();
out[now]=clock++;
if(s.empty()){
break;
}
now=s.top();
}
}
}
int main()
{
int t;
ka=0;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&C[i]);
if(i==0)
child[i]=1;
else
child[i]=child[i-1]+C[i-1];
check[i]=child[i];
}
check[n]=check[n-1]+C[n-1];
solve();
int m;
scanf("%d",&m);
printf("Case %d:\n",++ka);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
if(a>=b||a>=n||in[a]>in[b]||out[a]<out[b]){
printf("No\n");
}
else
printf("Yes\n");
}
if(t!=0)
printf("\n");
}
return 0;
}