1. 程式人生 > >Gym - 101848C Object-Oriented Programming (樹鏈剖分+線段樹+動態開點)

Gym - 101848C Object-Oriented Programming (樹鏈剖分+線段樹+動態開點)

C. Object-Oriented Programming time limit per test 3.0 s memory limit per test 1024 MB input standard input output standard output

Functions overriding, is a well-known concept, when we are using inheritance in Object-Oriented Programming (OOP). For those who are not familiar with OOP, I will recall a few things to perhaps refresh your memory.

  • class has at most one parent class. When they do, they are called subclasses inheriting their parents. Subclasses also inherit all the functions declared in their parent classes, and also, all the functions inherited by parents' parents, and so on. Here, we refer to the ancestors as superclasses.
  • Subclasses can, of course, declare new functions, and also override the functions already declared in superclasses. This is called overriding.
  • When an instance of the subclass calls a function, it will first try to find the code in its own class body, and then its parent, and then its parent's parent, etc., until it reaches the root (the superclass of all classes). If the function has still not been found yet, a runtime error will be raised.

As you might have guessed, we are interested in finding out in which class the function is written when some instance of a particular class calls it.

Input

The input is in the following format:

n (2 ≤ n ≤ 105) is the number of classes. Classes are numbered from 1 to n

pi (1 ≤ pi ≤ i - 1) is the parent class of class i. Class 1 is the root class, superclass of all classes. It has no parent.

ti denotes the number of functions written in class i, including both new functions and overriding functions. Then follows ai1, ai2, ..., aiti a list of these functions. Functions are also denoted using positive integers. It's guaranteed that every number will appear at most once in one list. 1 ≤ aij ≤ 106, 0 ≤ ti ≤ 106, .

q (1 ≤ q ≤ 105) is the query number. Then follows q queries. uiri (1 ≤ ui ≤ n1 ≤ ri ≤ 106) is the i-th query, asking when an instance of class ui calls function ri, in which class is this function written?

Output

For each query, print answer. If it is illegal, that is, a "runtime error" is raised, then output  - 1.

Example input Copy
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 Copy
-1
3
4
-1
Note

The sample is equivalent to the following Java code.


class Class1 {
void function2() { System.out.println("1"); }
void function1() { System.out.println("1"); }
}

class Class2 extends Class1 {

}

class Class3 extends Class2 {
void function5() { System.out.println("3"); }
void function2() { System.out.println("3"); }
}

class Class4 extends Class3 {
void function4() { System.out.println("4"); }
void function5() { System.out.println("4"); }
}

class Class5 extends Class3 {
void function5() { System.out.println("5"); }
}

void test() {
new Class3().function4();
new Class5().function2();
new Class4().function5();
new Class1().function3();
}

Some of the tests in the raw problem package have been removed due to the "Maximal summary testset file size exceeded" error on Codeforces.

 

題意:

題面說的很複雜,但是我們可以將他轉換成一個比較直白的模型:

給你n個點,依此輸入n-1條邊,形成一棵樹。然後依此輸入n行,依此表示1-n這幾個點每個點含有哪幾個值(一個點可以包含多個值,也可以不包含值,如果一條路徑上,後面的點包含的值如果和前面點包含的值相同,在詢問時會覆蓋前面的),然後q個詢問,每個詢問輸入兩個值:u,r;詢問u到根節點路徑上哪個點包含r這個值(相同的值後面點覆蓋前面點),輸出這個點的座標。

思路:

我們對每個值建一棵樹,將包含這些值的點存進樹裡,點i就將樹上點i標為i,然後詢問u,r時,我們只要詢問第r棵樹上1-u上最大值就好了(用個鏈剖+線段樹就好了),建樹的話直接動態開點就行了不會超記憶體,這樣的話這道題就很好寫了。。

如果想到了思路就很好寫,之前想歪了思路,debug了半天都沒有得到想要的值。

實現程式碼:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int Max = 3e7+10;
const int M = 2e6+10;
const int MM = 2e6;
int ls[Max],rs[Max],sum[Max],root[Max],idx,ed[Max];
struct node{
    int to,next;
}e[M];
int cnt,cnt1,n;
int son[M],siz[M],head[M],fa[M],top[M],dep[M],tid[M],mx[M],rk[M];
void add(int u,int v){
    e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
}

void dfs1(int u,int faz,int deep){
    dep[u] = deep;
    fa[u] = faz;
    siz[u] = 1;
    for(int i = head[u];i;i = e[i].next){
        int v = e[i].to;
        if(v == faz) continue;
        dfs1(v,u,deep+1);
        siz[u] += siz[v];
        if(siz[v] > siz[son[u]]||son[u] == -1)
            son[u] = v;
    }
}

void dfs2(int u,int t){
    top[u] = t;
    mx[u] = cnt1;
    tid[u] = cnt1;
    rk[cnt1] = u;
    cnt1++;
    if(son[u] == -1) return ;
    dfs2(son[u],t),mx[u] = max(mx[u],mx[son[u]]);
    for(int i = head[u];i;i=e[i].next){
        int v = e[i].to;
        if(v != fa[u]&&v != son[u])
            dfs2(v,v),mx[u] = max(mx[u],mx[v]);
    }
}

void update(int &k,int l,int r,int p,int num){
    if(!k){  
        k = ++idx;
        sum[k] = num;
    }
    sum[k] = max(sum[k],num);
    if(l == r)
        return ;
    int m = (l + r) >> 1;
    if(p <= m) update(ls[k],l,m,p,num);
    else update(rs[k],m+1,r,p,num);
}

int query(int k,int L,int R,int l,int r){
    if(!k) return 0;
    if(L <= l&&R >= r){
        return sum[k];
    }
    int m = (l + r) >> 1;
    int ans = 0;
    if(L <= m) ans = max(ans,query(ls[k],L,R,l,m));
    if(R > m) ans = max(ans,query(rs[k],L,R,m+1,r));
    return ans;
}

int solve(int x,int y,int rt){
    int fx = top[x],fy = top[y];
    int ans = 0;
    while(fx != fy){
        if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
        ans = max(ans,query(root[rt],tid[fx],tid[x],1,MM));
        x = fa[fx]; fx = top[x];
    }
    if(dep[x] > dep[y]) swap(x,y);
    ans = max(ans,query(root[rt],tid[x],tid[y],1,MM));
    return ans;
}

int main()
{
    int x,k,q,t,n;
    idx = 0;
    cnt1 = 1; cnt = 1;
    root[0] = 0,sum[0] = 0;
    scanf("%d",&n);
    memset(son,-1,sizeof(son));
    for(int i = 2;i <= n;i ++){
        scanf("%d",&x);
        add(x,i); add(i,x);
    }
    dfs1(1,0,1); dfs2(1,0);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&t);
        for(int j = 1;j <= t;j ++){
            scanf("%d",&x);
            update(root[x],1,MM,tid[i],i);
        }
    }
    scanf("%d",&q);
    while(q--){
        scanf("%d %d",&k,&x);
        //cout<<"kk: "<<k<<" "<<root[k]<<endl;
        int num = solve(1,k,x);
        if(num == 0) num = -1;
        printf("%d\n",num);
    }
    return 0;
}