pair<size_t, size_t> lowerb(size_t node, size_t L, size_t R, size_t rl, size_t rr, pair<size_t, size_t> minval) { if (rl <= L and R <= rr) { auto it = std::lower_bound(segm[node].begin(), segm[node].end(), minval); if (it == segm[node].end()) return make_pair(SIZE_MAX, SIZE_MAX); else return *it; } if (R <= rl or rr <= L) return make_pair(SIZE_MAX, SIZE_MAX); size_t mid = L + (R - L) / 2; return min(lowerb(2 * node + 1, L, mid, rl, rr, minval) ,lowerb(2 * node + 2, mid, R, rl, rr, minval)); }
/* * Blocked Jacobi solver: one iteration step */ double relax_jacobi (double *u, double *utmp, unsigned sizex, unsigned sizey) { double diff, sum=0.0; int howmany=omp_get_max_threads(); #pragma omp parallel reduction(+:sum) { for (int blockid = 0; blockid < howmany; ++blockid) { int i_start = lowerb(blockid, howmany, sizex); int i_end = upperb(blockid, howmany, sizex); for (int i=max(1, i_start); i<= min(sizex-2, i_end); i++) { #pragma omp for nowait private(diff) for (int j=1; j<= sizey-2; j++) { utmp[i*sizey+j]= 0.25 * ( u[ i*sizey + (j-1) ]+ // left u[ i*sizey + (j+1) ]+ // right u[ (i-1)*sizey + j ]+ // top u[ (i+1)*sizey + j ]); // bottom diff = utmp[i*sizey+j] - u[i*sizey + j]; sum += diff * diff; } } } } return sum; }
/* * Blocked Gauss-Seidel solver: one iteration step */ double relax_gauss (double *u, unsigned sizex, unsigned sizey) { double unew, diff, sum = 0.0; int howmany = omp_get_max_threads(); int numBlocs = 8; int blocsProcesats[howmany]; for(int i = 0; i < howmany; ++i) blocsProcesats[i] = 0; #pragma omp parallel for schedule(static) private(diff,unew) reduction(+: sum) for(int i = 0; i < howmany; i++){ int ii_start = lowerb(i,howmany,sizex); int ii_end = upperb(i,howmany,sizex); for (int j = 0; j < numBlocs; j++){ int jj_start = lowerb(j,numBlocs,sizey); int jj_end = upperb(j,numBlocs,sizey); if(i > 0){ while(blocsProcesats[i-1]<=j){ #pragma omp flush } } for(int ii = max(1,ii_start); ii<= min(sizex-2, ii_end); ii++){ for(int jj= max(1,jj_start); jj<= min(sizey-2, jj_end); jj++){ unew = 0.25* (u[ii * sizey + (jj-1)] + // left u[ii * sizey + (jj+1)] + // right u[(ii-1) * sizey + jj] + // top u[(ii+1) * sizey + jj]); // bottom diff = unew - u[ii * sizey + jj]; sum+= diff*diff; u[ii*sizey + jj] = unew; } } ++blocsProcesats[i]; #pragma omp flush } } return sum; }
int main() { std::iostream::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); size_t n, q; cin >> n >> q; for (size_t i = 1; i != n; ++i) graph[input<size_t>() - 1].push_back(i); dfs(0); buildseg(0, 0, MAXN); for (size_t i = 0; i != q; ++i) { size_t v = input<size_t>() - 1; cout << lowerb(0, 0, MAXN, times[v].first, times[v].second, make_pair((sizes[v] + 1) / 2, 0)).second + 1 << "\n"; } return 0; }