专栏文章
题解:P14521 【MX-S11-T2】加减乘除
P14521题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @min6vmaq
- 此快照首次捕获于
- 2025/12/01 21:32 3 个月前
- 此快照最后确认于
- 2025/12/01 21:32 3 个月前
容易发现对于树上的每个点,能到达它的 的值是一个区间,而这个区间是好求的。
假设我们已经求出了 的区间 ,而从根到 这条路径上要加上的 之和为 ,则合法的 需要满足: 以及 ,取这两个区间的交集即可得到 的区间 。
对于询问,就是要求有多少 满足 ,一个简单的做法是将所有的询问的 与所有的 放到一起离散化,那么一个数 的答案即为满足 的 的数量减去满足 的 的数量,这两个值对应的是离散化后的一个前缀。
CPP#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";
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...