bzoj4154
kdtree
转换一下,看成点,第一位dfs序,第二维深度,那么满足在子树内dfs序限制,然后kdtree上打标记就行了。
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 5, mod = 1e9 + 7; int rd() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } int n, c, q, root, d, dfs_clock; int dep[N], in[N], out[N]; vector<int> G[N]; struct data { int lc, rc, c, tag, p[2], mx[2], mn[2]; bool friend operator < (const data &a, const data &b) { return a.p[d] == b.p[d] ? a.p[d ^ 1] < b.p[d ^ 1] : a.p[d] < b.p[d]; } } a[N]; void update(int x) { int lc = a[x].lc, rc = a[x].rc; for(int i = 0; i < 2; ++i) { a[x].mn[i] = min(a[x].p[i], min(a[lc].mn[i], a[rc].mn[i])); a[x].mx[i] = max(a[x].p[i], max(a[lc].mx[i], a[rc].mx[i])); } } int build(int l, int r, int D) { if(l > r) return 0; d = D; int mid = (l + r) >> 1; nth_element(a + l, a + mid, a + r + 1); a[mid].lc = build(l, mid - 1, D ^ 1); a[mid].rc = build(mid + 1, r, D ^ 1); a[mid].c = 1; a[mid].tag = 0; update(mid); return mid; } void pushdown(int x) { if(!a[x].tag) return; int lc = a[x].lc, rc = a[x].rc; if(lc) a[lc].tag = a[lc].c = a[x].tag; if(rc) a[rc].tag = a[rc].c = a[x].tag; a[x].tag = 0; } bool In(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2) { return X1 >= x1 && Y1 >= y1 && X2 <= x2 && Y2 <= y2; } bool Out(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2) { return x1 > X2 || x2 < X1 || y1 > Y2 || y2 < Y1; } int query(int k, int x, int y) { if(!k || Out(x, y, x, y, a[k].mn[0], a[k].mn[1], a[k].mx[0], a[k].mx[1])) return 0; pushdown(k); if(x == a[k].p[0] && y == a[k].p[1]) return a[k].c; return query(a[k].lc, x, y) + query(a[k].rc, x, y); } void modify(int k, int x1, int y1, int x2, int y2, int c) { if(!k || Out(x1, y1, x2, y2, a[k].mn[0], a[k].mn[1], a[k].mx[0], a[k].mx[1])) return; pushdown(k); if(In(x1, y1, x2, y2, a[k].mn[0], a[k].mn[1], a[k].mx[0], a[k].mx[1])) { a[k].tag = a[k].c = c; return; } if(In(x1, y1, x2, y2, a[k].p[0], a[k].p[1], a[k].p[0], a[k].p[1])) a[k].c = c; modify(a[k].lc, x1, y1, x2, y2, c); modify(a[k].rc, x1, y1, x2, y2, c); } void dfs(int u) { a[u].p[0] = a[u].mn[0] = a[u].mx[0] = dep[u]; a[u].p[1] = a[u].mn[1] = a[u].mx[1] = in[u] = ++dfs_clock; a[u].lc = a[u].rc = 0; for(int i = 0; i < G[u].size(); ++i) { dep[G[u][i]] = dep[u] + 1; dfs(G[u][i]); } out[u] = dfs_clock; } int main() { for(int i = 0; i < 2; ++i) a[0].mn[i] = 1e9, a[0].mx[i] = -1e9; int T = rd(); while(T--) { long long ans = 0; n = rd(); c = rd(); q = rd(); for(int i = 1; i <= n; ++i) G[i].clear(); for(int i = 2; i <= n; ++i) { int fa = rd(); G[fa].push_back(i); } dep[1] = 1; dfs(1); root = build(1, n, 0); for(long long i = 1; i <= q; ++i) { int a = rd(), l = rd(), c = rd(); int dd = query(root, in[a], dep[a]); if(c == 0) ans = (ans + (long long)query(root, dep[a], in[a]) * i) % mod; if(c > 0) modify(root, dep[a], in[a], min(dep[a] + l, n), out[a], c); } printf("%lld\n", ans); } return 0; }