QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#227615 | #7563. Fun on Tree | ucup-team2307 | WA | 0ms | 3624kb | C++14 | 5.2kb | 2023-10-27 19:48:07 | 2023-10-27 19:48:07 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(x) begin(x), end(x)
const ll inf = 1ll<<60;
struct Node {
array<ll, 2> val = {-inf, -1};
ll lazy = 0;
};
struct Tree {
int n;
vector<Node> tree;
Tree(int N) : n(N), tree(4 * n + 4) {}
void apply(int v, ll x, int len) {
tree[v].val[0] += x;
tree[v].lazy += x;
}
void push(int v, int len) {
apply(2*v, tree[v].lazy, (len + 1) / 2);
apply(2*v+1, tree[v].lazy, len / 2);
tree[v].lazy = 0;
}
void update(int v, int l, int r, int ql, int qr, ll x) {
if(qr < l || r < ql) return;
if(ql <= l && r <= qr) {
apply(v, x, r - l + 1);
return;
}
push(v, r - l + 1);
int m = (l + r) / 2;
update(2 * v, l, m, ql, qr, x);
update(2 * v + 1, m + 1, r, ql, qr, x);
tree[v].val = max(tree[2*v].val, tree[2*v+1].val);
}
void update(int v, int l, int r, int qp, array<ll, 2> x) {
if(qp < l || r < qp) return;
if(l == r) {
tree[v].val = x;
return;
}
push(v, r - l + 1);
int m = (l + r) / 2;
update(2 * v, l, m, qp, x);
update(2 * v + 1, m + 1, r, qp, x);
tree[v].val = max(tree[2*v].val, tree[2*v+1].val);
}
array<ll, 2> query(int v, int l, int r, int ql, int qr) {
if(qr < l || r < ql) return {-inf, -1};
if(ql <= l && r <= qr) {
return tree[v].val;
}
push(v, r - l + 1);
int m = (l + r) / 2;
return max(query(2 * v, l, m, ql, qr), query(2 * v + 1, m + 1, r, ql, qr));
}
array<ll, 2> query(int l, int r) { return query(1, 0, n - 1, l, r); }
void update(int l, int r, ll x) { update(1, 0, n - 1, l, r, x); }
void assign(int p, array<ll, 2> x) { update(1, 0, n - 1, p, x); }
};
int main() {
cin.tie(0)->sync_with_stdio(0);
// Tree st(10);
// for(int i = 0; i < 10; i++)
// cout << st.query(i, i) << " "; cout << endl;
// st.update(3, 5, 1);
// st.update(0, 3, 10);
// cout << st.query(4, 9) << endl;
int n, q;
cin >> n >> q;
vector<int> a(n);
for(auto &i : a) cin >> i;
vector<vector<array<int, 2>>> g(n);
for(int p, w, i = 1; i < n; i++) {
cin >> p >> w;
g[--p].push_back({i, w});
}
vector<int> par(n), sz(n);
vector<ll> h(n);
auto sizes = [&](auto self, int v) -> void {
sz[v] = 1;
for(auto &P : g[v]) {
auto [i, w] = P;
par[i] = v;
h[i] = h[v] + w;
self(self, i);
sz[v] += sz[i];
if(sz[i] > sz[g[v][0][0]])
swap(P, g[v][0]);
}
};
sizes(sizes, 0);
int timer = 0;
vector<int> tin(n), tout(n), head(n);
auto hld = [&](auto self, int v) -> void {
tin[v] = timer++;
for(auto [i, w] : g[v]) {
head[i] = i == g[v][0][0] ? head[v] : i;
self(self, i);
}
tout[v] = timer;
};
hld(hld, 0);
Tree seg_da(n), seg_hld(n);
for(int i = 0; i < n; i++) {
seg_da.assign(tin[i], {h[i] - a[i], i});
}
auto all_but = [&](int v, int son) {
if(son == -1) {
return seg_da.query(tin[v], tout[v] - 1);
} else {
return max(seg_da.query(tin[v], tin[son] - 1),
seg_da.query(tout[son], tout[v] - 1));
}
};
for(int i = 0; i < n; i++) {
auto T = all_but(i, sz[i] == 1 ? -1 : g[i][0][0]);
T[0] -= 2*h[i];
seg_hld.assign(tin[i], T);
}
auto update = [&](int v, ll x) {//sulfur content increases by x in subtree of v
seg_da.update(tin[v], tout[v] - 1, -x);
seg_hld.update(tin[v], tout[v] - 1, -x);
while(true) {
v = head[v];
if(!v) break;
v = par[v];
auto T = all_but(v, g[v][0][0]);
T[0] -= 2*h[v];
seg_hld.assign(tin[v], T);
}
};
// for(int i = 0; i < n; i++)
// cout << seg_da.query(i, i) << " "; cout << endl;
// cout << all_but(3, -1) - h[3] << endl;
auto query = [&](int v) -> array<ll, 2> {
array<ll, 2> ans = {-inf, -1};
ll son = -1, base = h[v];
while(true) {
if(son == -1) {//son
auto X = all_but(v, -1);
X[0] -= base;
ans = max(ans, X);
} else {//light edge case
auto X = all_but(v, son);
X[0] += base - 2*h[v];
ans = max(ans, X);
}
if(!v) break;
if(v != head[v]) {//heavy edge case
auto X = seg_hld.query(tin[head[v]], tin[v] - 1);
X[0] += base;
ans = max(ans, X);
}
son = head[v];
v = par[head[v]];
}
return ans;
};
int x, y, v;
while(q--) {
cin >> x >> y >> v;
--x, --y;
update(y, v);
auto A = query(x);
cout << A[1]+1 << " " << A[0] << '\n';
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3624kb
input:
6 6 1 1 4 5 1 4 1 5 2 0 3 2 4 1 5 6 3 2 -100000 1 2 100000 1 1 0 2 2 66 3 1 5 4 4 -3
output:
6 100005 6 10 6 10 1 4 1 -1 1 1
result:
ok 6 lines
Test #2:
score: 0
Accepted
time: 0ms
memory: 3620kb
input:
5 6 -10 0 2 -4 8 1 7 1 1 2 2 2 -2 1 1 100 2 1 -100 1 1 0 4 3 10 2 5 3 5 2 2
output:
4 -87 1 17 4 13 1 19 1 17 1 15
result:
ok 6 lines
Test #3:
score: -100
Wrong Answer
time: 0ms
memory: 3556kb
input:
6 3 0 0 0 0 0 0 1 10 1 10 1 -100 4 10 4 11 1 1 0 4 1 0 1 4 1000
output:
3 10 6 11 3 10
result:
wrong answer 1st lines differ - expected: '2 10', found: '3 10'