题解:P14521 【MX-S11-T2】加减乘除
szh_AK_all · · 题解
容易发现对于树上的每个点,能到达它的
假设我们已经求出了
对于询问,就是要求有多少
#include <bits/stdc++.h>
using namespace std;
int fa[500005];
vector<int>g[500005];
long long l[500005], r[500005];
long long L[500005], R[500005];
long long a[500005];
char op[500005];
long long b[2000005], c[2000005];
int k[2000005];
int cnt;
__int128 one = 1;
void dfs(int x, __int128 now) {
if (L[x] > R[x])
return;
b[++cnt] = L[x], k[cnt] = 1;
b[++cnt] = R[x], k[cnt] = 2;
for (int y : g[x]) {
long long ll = l[y], rr = r[y];
//ll<=p+a[x]<=rr,L[x]<=p<=R[x]
//p<=rr-a[x],p>=ll-a[x]
__int128 pp = now;
if (op[x] == '+')
pp += a[x];
else
pp -= a[x];
L[y] = max(one * L[x], ll - pp), R[y] = min(one * R[x], rr - pp);
dfs(y, pp);
}
}
long long as[1000005];
int xl[2000005], xr[2000005];
unordered_map<long long,int>da;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n, q;
cin >> n >> q;
for (int i = 2; i <= n; i++) {
cin >> fa[i] >> l[i] >> r[i];
g[fa[i]].push_back(i);
}
for (int i = 1; i <= n; i++)
cin >> op[i] >> a[i];
R[1] = 1e18;
L[1] = -1e18;
dfs(1, 0);
for (int i = 1; i <= q; i++) {
cin >> as[i];
b[++cnt] = as[i];
}
for (int i = 1; i <= cnt; i++)
c[i] = b[i];
sort(c + 1, c + cnt + 1);
int nn = unique(c + 1, c + cnt + 1) - (c + 1);
for (int i = 1; i <= cnt; i++) {
b[i] = lower_bound(c + 1, c + nn + 1, b[i]) - c;
if (k[i] == 1)
xl[b[i]]++;
if (k[i] == 2)
xr[b[i]]++;
}
for (int i = 1; i <= nn; i++) {
xl[i] += xl[i - 1];
xr[i] += xr[i - 1];
da[c[i]] = xl[i] - xr[i - 1];
}
for (int i = 1; i <= q; i++)
cout << da[as[i]] << "\n";
}