// list-of-leaves version #include #include #include #include using namespace std; struct Frontier { bool type_range; Frontier(int b, int e) : type_range(true), range_b(b), range_e(e) {} int range_b, range_e; Frontier() : type_range(false) {} Frontier(int leaf) : type_range(false), leaves(1,leaf) {} list leaves; }; int main() { int T; cin >> T; for( int caseNo=1; caseNo<=T; ++caseNo ) { // Input (numbers of children) ///////////////////////////////////////// vector C; { int N; cin >> N; while(N--) {int c; cin>>c; C.push_back(c);} } // Construct information on tree /////////////////////////////////////// vector parent; // parent of each acm { parent.resize( accumulate(C.begin(), C.end(), 1) ); int bf_no = 1; for(int p=0; p!=C.size(); bf_no+=C[p],++p) for(int c=0; c leaves; // list of leaves, left-to-right { list f( 1, Frontier(0,1) ); int bf_no = 1; while( f.size()>1 || f.front().type_range ) { list new_f; for(list::iterator it=f.begin(); it!=f.end(); ++it) if( it->type_range ) for(int n=it->range_b; nrange_e; ++n) if( n0 ) new_f.push_back( Frontier(bf_no, bf_no+C[n]) ), bf_no+=C[n]; else if( new_f.empty() || new_f.back().type_range ) new_f.push_back( Frontier(n) ); else new_f.back().leaves.push_back( n ); else { if( new_f.empty() || new_f.back().type_range ) new_f.push_back( Frontier() ); // the use of splice here has a critical efficiency effect. new_f.back().leaves.splice( new_f.back().leaves.end(), it->leaves ); } f.swap(new_f); } leaves = vector(f.front().leaves.begin(), f.front().leaves.end()); } vector range_l( parent.size() ); // range labeling vector range_r( parent.size(), -1 ); { for(int i=0; i!=leaves.size(); ++i) range_l[leaves[i]] = range_r[leaves[i]] = i; for(int n=parent.size()-1; n>=1; --n ) { range_l[parent[n]] = range_l[n]; if( range_r[parent[n]] == -1 ) range_r[parent[n]] = range_r[n]; } } // Answer for each query ... //////////////////////////////////////////// int count = 0; int M; cin >> M; while(M--) { int a, b; cin >> a >> b; if( range_l[a]<=range_l[b] && range_r[b]<=range_r[a] && a < b ) count++; } // Output /////////////////////////////////////////////////////////////// cout << count << endl; } }