Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #define debug(tl) cerr<<#tl<<' '<<tl<<'\n';
- #include "bits/stdc++.h"
- using namespace std;
- #define all(d) d.begin(), d.end()
- #define int long long
- typedef long long ll;
- typedef pair<ll, ll> pll;
- typedef long double ld;
- vector<vector<ll>> gr;
- vector<int> head, siz, tin, tout, parent, a;
- const int inf = 1e13;
- vector<ll> sums, us, ans;
- struct segtree {
- vector<int> t, mod;
- int n;
- segtree() {}
- void init(int _n) {
- n = _n;
- mod.resize(4 * n + 100, 0);
- t.resize(4 * n + 100, inf);
- }
- void push(ll v) {
- t[v] += mod[v];
- if (v * 2 + 1 > (ll)t.size()) {
- mod[v] = 0;
- return;
- }
- mod[v * 2] += mod[v];
- mod[v * 2 + 1] += mod[v];
- mod[v] = 0;
- }
- void build(int v, int tl, int tr, vector<int>& a) {
- if (tl == tr) {
- t[v] = a[tl];
- return;
- }
- int tm = (tl + tr) / 2;
- build(v * 2, tl, tm, a);
- build(v * 2 + 1, tm + 1, tr, a);
- t[v] = min(t[v * 2], t[v * 2 + 1]);
- }
- void update(int v, int tl, int tr, int l, int r, int add) {
- push(v);
- if (tl > r || tr < l) {
- return;
- }
- if (tl >= l && tr <= r) {
- mod[v] += add;
- push(v);
- return;
- }
- int mid = (tl + tr) / 2;
- push(v * 2);
- push(v * 2 + 1);
- update(v * 2, tl, mid, l, r, add);
- update(v * 2 + 1, mid + 1, tr, l, r, add);
- t[v] = min(t[v * 2], t[v * 2 + 1]);
- }
- int get(int v, int tl, int tr, int pos) {
- push(v);
- if (tl == tr) {
- return t[v];
- }
- int tm = (tl + tr) / 2;
- if (pos <= tm) {
- return get(v * 2, tl, tm, pos);
- }
- else {
- return get(v * 2 + 1, tm + 1, tr, pos);
- }
- }
- int get_mn(int v, int tl, int tr, int l, int r) {
- push(v);
- if (tl > r || tr < l) {
- return inf;
- }
- if (tl >= l && tr <= r) {
- return t[v];
- }
- int tm = (tl + tr) / 2;
- push(v);
- push(v * 2);
- push(v * 2 + 1);
- return min(get_mn(v * 2, tl, tm, l, r), get_mn(v * 2 + 1, tm + 1, tr, l, r));
- }
- };
- int t = 0;
- void dfs1(int v, int p) {
- siz[v] = 1;
- for (int& u : gr[v]) {
- if (u == p) {
- swap(u, gr[v].back());
- gr[v].pop_back();
- break;
- }
- }
- parent[v] = (p == -1 ? v : p);
- for (int& u : gr[v]) {
- dfs1(u, v);
- siz[v] += siz[u];
- if (siz[u] > siz[gr[v][0]]) {
- swap(gr[v][0], u);
- }
- }
- }
- void dfs2(int v) {
- tin[v] = t++;
- a.push_back(us[v]);
- for (int& u : gr[v]) {
- if (u == gr[v][0]) {
- head[u] = head[v];
- }
- else {
- head[u] = u;
- }
- dfs2(u);
- }
- tout[v] = t;
- }
- bool is_in_sector(int u, int v) {
- return tin[u] <= tin[v] && tin[v] < tout[u];
- }
- void up(int& u, int& v, int& ans, segtree& Euler) {
- while (!is_in_sector(head[u], v)) {
- ans = min(ans, Euler.get_mn(1, 0, Euler.n - 1, tin[head[u]], tin[u]));
- u = parent[head[u]];
- }
- }
- int get_min(int u, int v, segtree &Euler) {
- int ans = inf;
- up(u, v, ans, Euler);
- up(v, u, ans, Euler);
- if (!is_in_sector(u, v)) {
- swap(u, v);
- }
- ans = min(ans, Euler.get_mn(1, 0, Euler.n - 1, tin[u], tin[v]));
- return ans;
- }
- void upd(int& u, int& v, int x, segtree& Euler) {
- while (!is_in_sector(head[u], v)) {
- Euler.update(1, 0, Euler.n - 1, tin[head[u]], tin[u], x);
- u = parent[head[u]];
- }
- }
- void update(int u, int v, int x, segtree& Euler) {
- upd(u, v, x, Euler);
- upd(v, u, x, Euler);
- if (!is_in_sector(u, v)) {
- swap(u, v);
- }
- Euler.update(1, 0, Euler.n - 1, tin[u], tin[v], x);
- }
- vector<ll> l, r, c;
- vector<multiset<pll>> mrg;// first - c, second - num of vertex
- // будем в вершину приливать значения сыновей
- // значения : сортировка в сету по стоимост (С) , второй элемент : кол во раз которой мы можем использовать эту стоимость
- // мы можем не зная ответа знать сколько максимум можно использовать стоимость из сыновей поддерева
- bool ok;
- void dfs(ll v, ll p, segtree &Euler) {
- if (!ok) {
- return;
- }
- for (ll& u : gr[v]) {
- if (u != p) {
- dfs(u, v, Euler);
- sums[v] += sums[u];
- if ((int)mrg[v].size() < (int)mrg[u].size()) {
- mrg[v].swap(mrg[u]);
- }
- for (auto& it : mrg[u]) {
- mrg[v].insert(it);
- }
- mrg[u].clear();
- }
- }
- mrg[v].insert({ c[v],v });
- if (sums[v] < l[v]) {
- while (!mrg[v].empty() && sums[v] < l[v]) {
- auto it = mrg[v].begin();
- pll x = *it;
- mrg[v].erase(mrg[v].begin());
- ll have = get_min(x.second, 0, Euler);
- ll need = min(have, l[v] - sums[v]);
- ans[x.second] += need;
- sums[v] += need;
- update(x.second, 0, -need, Euler);
- if (need < have) {
- mrg[v].insert(x);
- }
- }
- if (sums[v] < l[v]) {
- //ll gg = mrg[v].size();
- ok = false;
- return;
- }
- }
- }
- // нужно насчитать предков с минимальой суммой
- void precalc1(ll v, ll p) {
- ll suml = 0;
- if (!ok)return;
- for (ll& u : gr[v]) {
- if (u != p) {
- precalc1(u, v);
- suml += l[u];
- }
- }
- if (suml > r[v]) {
- ok = false;
- return;
- }
- us[v] = r[v];
- }
- void clean() {
- t = 0;
- ok = 1;
- gr.clear(), siz.clear();
- tin.clear(), tout.clear();
- parent.clear(), a.clear();
- sums.clear(), us.clear();
- ans.clear(), head.clear();
- l.clear(), r.clear(), c.clear(), mrg.clear();
- }
- signed main() {
- #ifdef _DEBUG
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- ll tt;
- cin >> tt;
- while (tt--) {
- ok = true;
- ll n;
- cin >> n;
- clean();
- us.resize(n), mrg.resize(n), gr.resize(n), l.resize(n), r.resize(n), c.resize(n), sums.resize(n);
- tin.resize(n), tout.resize(n), siz.resize(n), head.resize(n), parent.resize(n);
- for (ll i = 1; i < n; i++) {
- ll p;
- cin >> p; p--;
- gr[p].push_back(i);
- gr[i].push_back(p);
- }
- for (ll i = 0; i < n; i++) {
- cin >> c[i];
- }
- for (ll i = 0; i < n; i++) {
- cin >> l[i] >> r[i];
- }
- precalc1(0, -1);
- if (!ok) {
- cout << "-1\n";
- continue;
- }
- segtree Euler;
- dfs1(0, -1);
- dfs2(0);
- Euler.init((int)a.size());
- Euler.build(1, 0, Euler.n - 1, a);
- ans.clear();
- ans.resize(n);
- dfs(0, -1, Euler);
- if (!ok) {
- cout << "-1\n";
- continue;
- }
- ll anssum = 0;
- for (ll i = 0; i < ans.size(); i++) {
- anssum += ans[i] * c[i];
- }
- cout << anssum << '\n';
- for (ll i = 0; i < ans.size(); i++) {
- cout << ans[i] << ' ';
- }
- cout << '\n';
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement