错在这组样例,发现是离散化之后,对k访问的时候也是应该访问离散化之后的k。
12 4 1 1 2 2 5 5 4 4 3 3 2 1 1 3 3 5 7 7 9 9 9 11 11 1 10 3 10 3 11 2 4
发现主席树大概还真的要开够log倍,少一点都不行,那干脆开大一点。
#include<bits/stdc++.h> #define mid ((l+r)>>1) using namespace std; const int MAXN = 100000 + 5; int a[MAXN], b[MAXN]; vector<int> E[MAXN]; int siz[MAXN], tid[MAXN], rnk[MAXN], cnt; int T[MAXN], tcnt; int sum[MAXN << 5], L[MAXN << 5], R[MAXN << 5]; void init(int n) { for(int i = 1; i <= n; ++i) E[i].clear(); cnt = 0; tcnt = 0; } void dfs(int u) { siz[u] = 1; tid[u] = ++cnt; rnk[cnt] = u; for(auto v : E[u]) { dfs(v); siz[u] += siz[v]; } } inline int build(int l, int r) { int rt = ++tcnt; sum[rt] = 0; if(l < r) { L[rt] = build(l, mid); R[rt] = build(mid + 1, r); } return rt; } inline int update(int pre, int l, int r, int x) { int rt = ++tcnt; R[rt] = R[pre]; L[rt] = L[pre]; sum[rt] = sum[pre] + 1; if(l < r) { if(x <= mid) L[rt] = update(L[pre], l, mid, x); else R[rt] = update(R[pre], mid + 1, r, x); } return rt; } //查询[u-1,v]中不超过k的数的个数 inline int query2(int u, int v, int l, int r, int k) { int res = 0; while(l < r && k < r) { if(k >= mid) { res += sum[L[v]] - sum[L[u]]; u = R[u], v = R[v], l = mid + 1; } else u = L[u], v = L[v], r = mid; } return res + (k >= l ? sum[v] - sum[u] : 0); } int main() { #ifdef Yinku freopen("Yinku.in", "r", stdin); #endif // Yinku int n, q, r = 1; while(~scanf("%d%d", &n, &q)) { init(n); for(int i = 2, f; i <= n; ++i) { scanf("%d", &f); E[f].push_back(i); } dfs(r); for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); b[i] = a[i]; } sort(b + 1, b + 1 + n); int cb = unique(b + 1, b + 1 + n) - b - 1; tcnt = 0; T[0] = build(1, cb); for(int i = 1; i <= n; i ++) { int t = lower_bound(b + 1, b + 1 + cb, a[rnk[i]]) - b; T[i] = update(T[i - 1], 1, cb, t); } while(q--) { int u, k; scanf("%d%d", &u, &k); k = upper_bound(b + 1, b + 1 + cb, k) - b - 1; int l = tid[u], r = tid[u] + siz[u] - 1; printf("%d\n", query2(T[l - 1], T[r], 1, cb, k)); } } return 0; }