bzoj3626
树链剖分+离线
思路很好
看见这种题肯定知道不能直接求,就得在lca上搞事情
将询问拆成两个,排序,然后离线不断从i=1-n到根的路径上全部+1,每次询问就询问从z到根的路径和
我们想一想,就可以知道z和i,将i到根的路径全部+1,那么lca的深度就是z到根的权值和,而且这个权值和满足可加性,那么我们把询问拆成两个,1-l-1,1-r,相减就是答案
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 50010, mod = 201314; int n, Q, tot, cnt; ll ans[N]; int dfn[N], top[N], size[N], son[N], fa[N], dep[N]; vector<int> G[N]; struct query { int p, z, id, add; bool friend operator < (query A, query B) { return A.p < B.p; } } q[N << 1]; struct seg { int tree[N << 2], tag[N << 2]; void pushdown(int x, int l, int r) { if(!tag[x]) return; int mid = (l + r) >> 1; tree[x << 1] += (mid - l + 1) * tag[x]; tree[x << 1 | 1] += (r - mid) * tag[x]; tag[x << 1] += tag[x]; tag[x << 1 | 1] += tag[x]; tag[x] = 0; } void update(int l, int r, int x, int a, int b, int delta) { if(l > b || r < a) return; if(l >= a && r <= b) { tag[x] += delta; tree[x] += (r - l + 1) * delta; return; } pushdown(x, l, r); int mid = (l + r) >> 1; update(l, mid, x << 1, a, b, delta); update(mid + 1, r, x << 1 | 1, a, b, delta); tree[x] = tree[x << 1] + tree[x << 1 | 1]; } int query(int l, int r, int x, int a, int b) { if(l > b || r < a) return 0; if(l >= a && r <= b) return tree[x]; pushdown(x, l, r); int mid = (l + r) >> 1; return (query(l, mid, x << 1, a, b) + query(mid + 1, r, x << 1 | 1, a, b)); } } t; void dfs(int u, int last) { size[u] = 1; for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == last) continue; dep[v] = dep[u] + 1; fa[v] = u; dfs(v, u); size[u] += size[v]; if(size[v] > size[son[u]]) son[u] = v; } } void dfs(int u, int last, int acs) { dfn[u] = ++cnt; top[u] = acs; if(son[u]) dfs(son[u], u, acs); for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(v == last || v == son[u]) continue; dfs(v, u, v); } } void change(int u) { while(top[u] != 1) { t.update(1, n, 1, dfn[top[u]], dfn[u], 1); u = fa[top[u]]; } t.update(1, n, 1, 1, dfn[u], 1); } ll que(int u) { ll ret = 0; while(top[u] != 1) { ret += t.query(1, n, 1, dfn[top[u]], dfn[u]); u = fa[top[u]]; } ret += t.query(1, n, 1, 1, dfn[u]); return ret; } int main() { scanf("%d%d", &n, &Q); for(int i = 2; i <= n; ++i) { int u; scanf("%d", &u); ++u; G[i].push_back(u); G[u].push_back(i); } for(int i = 1; i <= Q; ++i) { int l, r, z; scanf("%d%d%d", &l, &r, &z); ++l; ++r; ++z; q[++tot].id = i; q[tot].p = l - 1; q[tot].z = z; q[tot].add = -1; q[++tot].id = i; q[tot].p = r; q[tot].z = z; q[tot].add = 1; } dfs(1, 0); dfs(1, 0, 1); sort(q + 1, q + tot + 1); int p = 0; while(q[p + 1].p == 0) ++p; for(int i = 1; i <= n; ++i) { change(i); while(q[p + 1].p == i) { ++p; ans[q[p].id] += que(q[p].z) * q[p].add; } } for(int i = 1; i <= Q; ++i) printf("%lld\n", (ans[i] % mod + mod) % mod); return 0; }