mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
213 lines
5.9 KiB
C++
213 lines
5.9 KiB
C++
|
#include <map>
|
||
|
#include <vector>
|
||
|
#include <cstdio>
|
||
|
#include <cstring>
|
||
|
#include <algorithm>
|
||
|
using namespace std ;
|
||
|
typedef long long LL ;
|
||
|
#pragma comment(linker, "/STACK:16777216")
|
||
|
#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
|
||
|
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
|
||
|
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
|
||
|
#define clr( a , x ) memset ( a , x , sizeof a )
|
||
|
#define mid ( ( l + r ) >> 1 )
|
||
|
const int MAXN = 100005 ;
|
||
|
const int MAXE = 100005 ;
|
||
|
struct Node {
|
||
|
Node* c[2] ;
|
||
|
int sum ;
|
||
|
} ;
|
||
|
struct Edge {
|
||
|
int v , n ;
|
||
|
Edge () {}
|
||
|
Edge ( int v , int n ) : v ( v ) , n ( n ) {}
|
||
|
} ;
|
||
|
struct Seg {
|
||
|
int L , R ;
|
||
|
Seg () {}
|
||
|
Seg ( int L , int R ) : L ( L ) , R ( R ) {}
|
||
|
} ;
|
||
|
struct HeavyLightDecompose {
|
||
|
Edge E[MAXE] ;
|
||
|
int H[MAXN] , cntE ;
|
||
|
int pre[MAXN] ;
|
||
|
int pos[MAXN] ;
|
||
|
int dep[MAXN] ;
|
||
|
int siz[MAXN] ;
|
||
|
int son[MAXN] ;
|
||
|
int top[MAXN] ;
|
||
|
int val[MAXN] ;
|
||
|
int tree_ ;
|
||
|
void clear () {
|
||
|
tree_idx = 0 ;
|
||
|
dep[1] = 0 ;
|
||
|
pre[1] = 0 ;
|
||
|
siz[0] = 0 ;
|
||
|
cntE = 0 ;
|
||
|
clr ( H , -1 ) ;
|
||
|
}
|
||
|
void addedge ( int u , int v ) {
|
||
|
E[cntE] = Edge ( v , H[u] ) ;
|
||
|
H[u] = cntE ++ ;
|
||
|
}
|
||
|
void dfs ( int u ) {
|
||
|
siz[u] = 1 ;
|
||
|
son[u] = 0 ;
|
||
|
for ( int i = H[u] ; ~i ; i = E[i].n ) {
|
||
|
int v = E[i].v ;
|
||
|
if ( v == pre[u] ) continue ;
|
||
|
pre[v] = u ;
|
||
|
dep[v] = dep[u] + 1 ;
|
||
|
dfs ( v ) ;
|
||
|
siz[u] += siz[v] ;
|
||
|
if ( siz[v] > siz[son[u]] ) son[u] = v ;
|
||
|
}
|
||
|
}
|
||
|
void rebuild ( int u , int top_ ) {
|
||
|
top[u] = top_ ;
|
||
|
pos[u] = ++ tree_ ;
|
||
|
if ( son[u] ) rebuild ( son[u] , top_ ) ;
|
||
|
for ( int i = H[u] ; ~i ; i = E[i].n ) {
|
||
|
int v = E[i].v ;
|
||
|
if ( v != pre[u] && v != son[u] ) {
|
||
|
rebuild ( v , v ) ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} ;
|
||
|
Node pool[MAXN * 50] ;
|
||
|
Node* root[MAXN] ;
|
||
|
Node* cur ;
|
||
|
HeavyLightDecompose T1 , T2 ;
|
||
|
Seg seg[MAXN] ;
|
||
|
int top ;
|
||
|
int cnt ;
|
||
|
int n1 , n2 , q ;
|
||
|
map < int , int > mp ;
|
||
|
void clear () {
|
||
|
T1.clear () ;
|
||
|
T2.clear () ;
|
||
|
mp.clear () ;
|
||
|
cur = pool ;
|
||
|
}
|
||
|
void build ( Node* &now , int l , int r ) {
|
||
|
now = cur ++ ;
|
||
|
now->sum = 0 ;
|
||
|
if ( l == r ) return ;
|
||
|
int m = mid ;
|
||
|
build ( now->c[0] , l , m ) ;
|
||
|
build ( now->c[1] , m + 1 , r ) ;
|
||
|
}
|
||
|
void insert ( Node* &now , Node* old , int x , int v , int l , int r ) {
|
||
|
now = cur ++ ;
|
||
|
if ( l == r ) {
|
||
|
now->sum = old->sum + v ;
|
||
|
return ;
|
||
|
}
|
||
|
int m = mid ;
|
||
|
if ( x <= m ) {
|
||
|
now->c[1] = old->c[1] ;
|
||
|
insert ( now->c[0] , old->c[0] , x , v , l , m ) ;
|
||
|
} else {
|
||
|
now->c[0] = old->c[0] ;
|
||
|
insert ( now->c[1] , old->c[1] , x , v , m + 1 , r ) ;
|
||
|
}
|
||
|
now->sum = now->c[0]->sum + now->c[1]->sum ;
|
||
|
}
|
||
|
int query ( Node* now , Node* old , int x , int l , int r ) {
|
||
|
if ( x == 0 ) return 0 ;
|
||
|
int ans = 0 ;
|
||
|
while ( l < r ) {
|
||
|
int m = mid ;
|
||
|
if ( x <= m ) {
|
||
|
now = now->c[0] ;
|
||
|
old = old->c[0] ;
|
||
|
r = m ;
|
||
|
} else {
|
||
|
ans += now->c[0]->sum - old->c[0]->sum ;
|
||
|
now = now->c[1] ;
|
||
|
old = old->c[1] ;
|
||
|
l = m + 1 ;
|
||
|
}
|
||
|
}
|
||
|
ans += now->sum - old->sum ;
|
||
|
return ans ;
|
||
|
}
|
||
|
void dfs ( int u ) {
|
||
|
if ( mp.count ( T2.val[u] ) ) insert ( root[T2.pos[u]] , root[T2.pos[u] - 1] , mp[T2.val[u]] , 1 , 1 , cnt ) ;
|
||
|
else root[T2.pos[u]] = root[T2.pos[u] - 1] ;
|
||
|
if ( T2.son[u] ) dfs ( T2.son[u] ) ;
|
||
|
for ( int i = T2.H[u] ; ~i ; i = T2.E[i].n ) {
|
||
|
int v = T2.E[i].v ;
|
||
|
if ( v != T2.pre[u] && v != T2.son[u] ) {
|
||
|
dfs ( v ) ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void get_seg ( int x , int y ) {
|
||
|
top = 0 ;
|
||
|
while ( T1.pos[T1.top[x]] != T1.pos[T1.top[y]] ) {
|
||
|
if ( T1.dep[T1.top[x]] < T1.dep[T1.top[y]] ) swap ( x , y ) ;
|
||
|
seg[top ++] = Seg ( T1.pos[T1.top[x]] , T1.pos[x] ) ;
|
||
|
x = T1.pre[T1.top[x]] ;
|
||
|
}
|
||
|
if ( T1.dep[x] > T1.dep[y] ) swap ( x , y ) ;
|
||
|
seg[top ++] = Seg ( T1.pos[x] , T1.pos[y] ) ;
|
||
|
}
|
||
|
int get_sum ( int x , int y ) {
|
||
|
int ans = 0 ;
|
||
|
while ( T2.pos[T2.top[x]] != T2.pos[T2.top[y]] ) {
|
||
|
if ( T2.dep[T2.top[x]] < T2.dep[T2.top[y]] ) swap ( x , y ) ;
|
||
|
rep ( i , 0 , top ) {
|
||
|
int L = seg[i].L ;
|
||
|
int R = seg[i].R ;
|
||
|
ans -= query ( root[T2.pos[x]] , root[T2.pos[T2.top[x]] - 1] , L - 1 , 1 , cnt ) ;
|
||
|
ans += query ( root[T2.pos[x]] , root[T2.pos[T2.top[x]] - 1] , R , 1 , cnt ) ;
|
||
|
}
|
||
|
x = T2.pre[T2.top[x]] ;
|
||
|
}
|
||
|
if ( T2.dep[x] > T2.dep[y] ) swap ( x , y ) ;
|
||
|
rep ( i , 0 , top ) {
|
||
|
int L = seg[i].L ;
|
||
|
int R = seg[i].R ;
|
||
|
ans -= query ( root[T2.pos[y]] , root[T2.pos[x] - 1] , L - 1 , 1 , cnt ) ;
|
||
|
ans += query ( root[T2.pos[y]] , root[T2.pos[x] - 1] , R , 1 , cnt ) ;
|
||
|
}
|
||
|
return ans ;
|
||
|
}
|
||
|
void solve () {
|
||
|
int u , v ;
|
||
|
clear () ;
|
||
|
cnt = n1 ;
|
||
|
For ( i , 2 , n1 ) {
|
||
|
scanf ( "%d" , &u ) ;
|
||
|
T1.addedge ( u , i ) ;
|
||
|
}
|
||
|
For ( i , 1 , n1 ) scanf ( "%d" , &T1.val[i] ) ;
|
||
|
scanf ( "%d" , &n2 ) ;
|
||
|
For ( i , 2 , n2 ) {
|
||
|
scanf ( "%d" , &u ) ;
|
||
|
T2.addedge ( u , i ) ;
|
||
|
}
|
||
|
For ( i , 1 , n2 ) scanf ( "%d" , &T2.val[i] ) ;
|
||
|
T1.dfs ( 1 ) ;
|
||
|
T1.rebuild ( 1 , 1 ) ;
|
||
|
For ( i , 1 , n1 ) mp[T1.val[i]] = T1.pos[i] ;
|
||
|
build ( root[0] , 1 , cnt ) ;
|
||
|
T2.dfs ( 1 ) ;
|
||
|
T2.rebuild ( 1 , 1 ) ;
|
||
|
dfs ( 1 ) ;
|
||
|
scanf ( "%d" , &q ) ;
|
||
|
while ( q -- ) {
|
||
|
scanf ( "%d%d" , &u , &v ) ;
|
||
|
get_seg ( u , v ) ;
|
||
|
scanf ( "%d%d" , &u , &v ) ;
|
||
|
int ans = get_sum ( u , v ) ;
|
||
|
printf ( "%d\n" , ans ) ;
|
||
|
}
|
||
|
}
|
||
|
int main () {
|
||
|
while ( ~scanf ( "%d" , &n1 ) ) solve () ;
|
||
|
return 0 ;
|
||
|
}
|