题目链接http://codeforces.com/gym/101848/problem/C
题意:
有n个类,每个类都定义了一些方法,而且每个类都会继承另一个类(1号类除外)。
q次询问,每次询问一个类调用一个方法,问所调用的方法是哪一个类里写的。所有申明的方法数不超过1e6。
题解:
大多是DFS写的,我这里提供一个主席树的方法。
每一个类建一个方法的线段树,记录的是最近申明的方法,也就是答案。
因为方法总数不超过1e6,所以最后空间大概是4e7级别。
而且线段树只有叶子节点才会有用,在这里的线段树只是起一个二分作用。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+7;
int t[N*40],rt[N],ls[N*40],rs[N*40],p[N],tot;
int upd(int o,int l,int r,int x,int y){
int now=++tot;
if(l==r){
t[now]=y;
return now;
}
ls[now]=ls[o];rs[now]=rs[o];
int m=l+r>>1;
if(x<=m) ls[now]=upd(ls[o],l,m,x,y);
else rs[now]=upd(rs[o],m+1,r,x,y);
return now;
}
int que(int o,int l,int r,int x){
if(l==r) return t[o];
int m=l+r>>1;
if(x<=m) return que(ls[o],l,m,x);
return que(rs[o],m+1,r,x);
}
int main(){
int n,q;
memset(t,-1,sizeof(t));
scanf("%d",&n);
for(int i=2,x;i<=n;i++){
scanf("%d",&p[i]);
}
int lst=0;
for(int i=1,m,x;i<=n;i++){
scanf("%d",&m);
rt[i]=rt[p[i]];
while(m--){
scanf("%d",&x);
rt[i]=upd(rt[i],1,N,x,i);
}
}
scanf("%d",&q);
int x,y;
while(q--){
scanf("%d%d",&x,&y);
printf("%d\n",que(rt[x],1,N,y));
}
}