太长了,不想写。
看到这个子树问题,很容易想到dfs序转区间。
再写写约束,发现有三个,并且满足容斥性。
于是排序搞掉一个,cdq搞掉一个,树状数组搞掉一个,贼好写。
主席树,K-D Tree当然也可以,有些复杂。
Code:
#include
#include
#define low(a) ((a) & -(a))
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int N = 3e5 + 5;
int n, m, Q, x, y, tq; ll ans[N];
int final[N], to[N], next[N], tot;
int dep[N], bz[N], p[N], q[N], td;
struct node {
int i, t, x, w;
} a[N];
void link(int x, int y) {
next[++ tot] = final[x], to[tot] = y, final[x] = tot;
next[++ tot] = final[y], to[tot] = x, final[y] = tot;
}
void dg(int x) {
bz[x] = 1; p[x] = ++ td;
for(int i = final[x]; i; i = next[i]) {
int y = to[i]; if(bz[y]) continue;
dep[y] = dep[x] + 1; dg(y);
}
q[x] = td;
}
int cmp(node a, node b) {
if(a.t < b.t) return 1;
if(a.t > b.t) return 0;
return a.i > b.i;
}
ll f[N];
void add(int x, int w) {
while(x <= n) f[x] += w, x += low(x);
}
ll find(int x) {
ll s = 0; while(x) s += f[x], x -= low(x);
return s;
}
int cmp2(node a, node b) {
return dep[a.x] + a.t > dep[b.x] + b.t;
}
void dg(int x, int y) {
if(x == y) return;
int m = x + y >> 1;
dg(x, m); dg(m + 1, y);
int l = x;
fo(i, m + 1, y) if(a[i].i) {
while(l <= m && a[l].t + dep[a[l].x] + 1 >= a[i].t + dep[a[i].x]) {
if(!a[l].i) add(p[a[l].x], a[l].w);
l ++;
}
ans[a[i].i] += find(q[a[i].x]) - find(p[a[i].x] - 1);
}
fo(i, x, l - 1) if(!a[i].i) add(p[a[i].x], -a[i].w);
sort(a + x, a + y + 1, cmp2);
}
int main() {
freopen("appletree.in", "r", stdin);
freopen("appletree.out", "w", stdout);
scanf("%d %d %d", &n, &m, &Q);
fo(i, 1, n) {
tq ++; a[tq].i = 0; a[tq].t = 0; a[tq].x = i;
scanf("%d", &a[tq].w);
}
fo(i, 1, n - 1) {
scanf("%d %d", &x, &y);
link(x, y);
}
dep[1] = 1; dg(1);
fo(i, 1, m) {
a[++ tq].i = 0;
scanf("%d %d %d", &a[tq].t, &a[tq].x, &a[tq].w);
}
fo(i, 1, Q) {
a[++ tq].i = i;
scanf("%d %d", &a[tq].t, &a[tq].x);
}
sort(a + 1, a + tq + 1, cmp);
dg(1, tq);
fo(i, 1, Q) printf("%lld\n", ans[i]);
}