NC25555. 华华和奕奕的旅行
描述
输入描述
第一行输入n
接下来n-1行,每行输入x,y,表示x管辖y。
接下来一行输入n个数表示每个地区的产水量,即w[i]。
接下来一行输入n个数表示每个地区的用水量,即c[i]。
输入Q
接下来Q行
每行先输入op,若op!=3,输入a,b
1<=n,Q<=1e5,0<=w[i],c[i]<=1e9
1<=x,y<=n,1<=a<=n,1<=b<=1e9
数据保证w[i]不会减为负数,且op==1的情况不超过500次
输出描述
对于每次询问,若所有地区都不缺水,输出"YES"
否则,输出"NO"
示例1
输入:
7 1 2 1 3 2 4 3 5 5 6 5 7 8 5 3 2 1 1 2 1 4 4 5 0 1 1 8 3 2 2 4 2 4 2 3 1 1 1 3 1 3 1 3
输出:
YES NO NO YES
C++14(g++5.4) 解法, 执行用时: 823ms, 内存消耗: 12892K, 提交时间: 2019-05-17 22:11:37
#include <bits/stdc++.h> using namespace std; const size_t maxn = 1 << 17; size_t father[maxn], fa[maxn]; vector<size_t> son[maxn]; int64_t w[maxn], c[maxn], a[maxn], b[maxn]; void find(size_t u, int64_t x) { if (!u) { b[0] -= x; return; } int64_t mi = min(x, b[fa[u]]); b[fa[u]] -= mi; x -= mi; if (x) { find(father[fa[u]], x); fa[u] = fa[father[fa[u]]]; } } int main() { size_t n; cin >> n; for (size_t i = 1; i != n; ++i) { size_t x, y; cin >> x >> y; son[x].emplace_back(y); father[y] = x; } vector<size_t> bfs(1, 1); for (size_t i = 0; i != bfs.size(); ++i) for (const auto& v : son[bfs[i]]) bfs.emplace_back(v); reverse(bfs.begin(), bfs.end()); for (size_t i = 1; i <= n; ++i) cin >> w[i]; for (size_t i = 1; i <= n; ++i) cin >> c[i]; for (size_t i = 1; i <= n; ++i) a[i] = w[i] - c[i]; bool check; auto build = [&] () { for (size_t i = 1; i <= n; ++i) b[i] = a[i], fa[i] = i; b[0] = 0; for (const auto& u : bfs) if (b[u] < 0) { b[father[u]] += b[u]; b[u] = 0; } // cout << "b : "; // for (size_t i = 0; i <= n; ++i) cout << b[i] << ' '; // cout << endl; check = b[0] < int64_t(0); }; build(); size_t Q; cin >> Q; while (Q--) { int op; cin >> op; if (op == 1) { size_t A; int64_t B; cin >> A >> B; a[A] += B; build(); } if (op == 2) { size_t A; int64_t B; cin >> A >> B; a[A] -= B; if (check) continue; find(A, B); check = b[0] < int64_t(0); } if (op == 3) { cout << (check ? "NO" : "YES") << endl; } } }
C++11(clang++ 3.9) 解法, 执行用时: 1498ms, 内存消耗: 8700K, 提交时间: 2019-05-28 09:52:16
#include<bits/stdc++.h> using namespace std; #define ll long long const int N = 100005; int n, num, q, cnt, p[N], f[N], fa[N], c[N], h[N], e[N], pre[N]; ll w[N], a[N]; void add(int x, int y){ e[++num]=y, pre[num]=h[x], h[x]=num;} int find(int x){ return f[x]==x?x:f[x]=find(f[x]);} void dfs(int u){ p[++cnt]=u; for(int i=h[u]; i; i=pre[i]) dfs(e[i]); } void rebuild(){ for(int i=1; i<=n; ++i) a[i]=c[i]; for(int i=n; i; --i){ int u=p[i]; if(a[u]>w[u]) a[f[u]=fa[u]]+=a[u]-w[u]; else f[u]=u; } for(int i=1; i<=n; ++i){ int u=p[i]; f[u]=f[f[u]]; } } int main() { scanf("%d", &n); for(int i=1, x, y; i<n; ++i) scanf("%d%d", &x, &y), add(x, y), fa[y]=x; for(int i=1; i<=n; ++i) scanf("%lld", w+i); for(int i=1; i<=n; ++i) scanf("%d", c+i); dfs(1), rebuild(); scanf("%d", &q); while(q--){ int opt, x, y; scanf("%d", &opt); if(opt==3) puts(a[1]>w[1]?"NO":"YES"); else{ scanf("%d%d", &x, &y); if(opt==1) w[x]+=y, rebuild(); else{ w[x]-=y; if(f[x]!=x) a[x=find(x)]+=y; while(x!=1 && a[x]>w[x]) f[x]=fa[x], a[find(x)]+=a[x]-w[x], x=f[x]; } } } return 0; }