题目链接:面向对象程序设计
描述
在面向对象程序设计中,常常会运用到函数的扩展与重写。当一个类继承某个类的时候,它可以调用所有父类可以调用的函数。它可以声明新的函数。当新的函数签名与父类的某个函数一致时,就会发生函数的覆盖(重写)。所以,在子类的实例调用某个函数时,它会调用最近的父类(有可能是它自己)的那个函数实现。
这里我们不考虑访问权限等情况,我们只关心某个类在调用某个函数时,这个函数是在哪个类中实现的。
Input
输入具有如下格式:
np2 p3 … pnt1 a11 a12 … a1t1t2 a21 a22 … a2t2⋮tn an1 an2 … antnqu1
r1u2 r2⋮uq rq解释与数据规模约定:
- n 表示有 n 个类,这些类从 1 到 n 编号。2≤n≤105。
- pi 表示第 i 个类的父类编号。1≤pi≤i−1。第 1 个类是所有类共同的祖先类,这个类没有父类。
- ti 表示在第 i 个类中定义了多少个函数,ai1,ai2,…,aiti 表示第 i 个类中的函数列表。同一个类的函数列表中不会出现两个相同的函数。1≤aij≤106。0≤ti≤106,∑ti≤106。
- q 表示询问个数。1≤q≤105。
- ui,ri 表示第 i 个询问,询问第 ui 个类的实例在调用 ri 函数时,调用的是哪个类中的版本。1≤ui≤n,1≤ri≤106。
Output
对于每个询问,输出答案。如果调用不合法(会导致编译错误),输出 −1。
input
5
1 2 3 3
2 2 1
0
2 5 2
2 4 5
1 5
4
3 4
5 2
4 5
1 3
output
-1
3
4
-1
思路
首先是题意,给了一个有n
个节点的树,保证根节点为1
,每一个节点可能控制着若干函数,最后有q
组询问,每组询问查询当前节点a
的第b
个函数被哪个节点控制,查询不合法就输出-1
.
我们用邻接表先把这个树和每一个查询存起来,然后用一遍dfs
,在遍历整个树的时候先查看当前节点控制着哪些函数,然后添加在对应的栈中去,然后查看当前节点是否有询问,如果有的时候就去栈中找答案。然后继续dfs
,在回溯的时候进行出栈操作吗,整个过程是离线的,只需要对一棵树进行一遍dfs
即可
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include <list>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=1e6+10;
struct node
{
int id,num;
node() {}
node(int _id,int _num)
{
id=_id;
num=_num;
}
};
vector<int>e[N];//邻接表存图
vector<int>T[N];//存储每个节点的函数
stack<int>s[N];
vector<node>query[N];//存储询问
int ans[N];//存储答案
void dfs(int u)
{
for(auto v:T[u])
s[v].push(u);//控制v函数的有哪些节点
for(auto now:query[u])
{
if(s[now.num].size()==0)
ans[now.id]=-1;
else
ans[now.id]=s[now.num].top();
}
for(auto v:e[u])
dfs(v);
for(auto v:T[u])//回溯的时候要出栈
s[v].pop();
}
int main()
{
int n,x,q,num;
scanf("%d",&n);
for(int i=2; i<=n; i++)
{
scanf("%d",&x);
e[x].push_back(i);
}
for(int i=1; i<=n; i++)
{
scanf("%d",&x);
while(x--)
{
scanf("%d",&num);
T[i].push_back(num);
}
}
scanf("%d",&q);
int a,b;
for(int i=1; i<=q; i++)
{
scanf("%d%d",&a,&b);
query[a].push_back(node(i,b));
}
dfs(1);
for(int i=1; i<=q; i++)
printf("%d\n",ans[i]);
return 0;
}