EOJ3562 面向对象程序设计(dfs,栈,离线处理)

题目链接:面向对象程序设计

描述

在面向对象程序设计中,常常会运用到函数的扩展与重写。当一个类继承某个类的时候,它可以调用所有父类可以调用的函数。它可以声明新的函数。当新的函数签名与父类的某个函数一致时,就会发生函数的覆盖(重写)。所以,在子类的实例调用某个函数时,它会调用最近的父类(有可能是它自己)的那个函数实现。

这里我们不考虑访问权限等情况,我们只关心某个类在调用某个函数时,这个函数是在哪个类中实现的。

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;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/80318137