QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#320997 | #7563. Fun on Tree | bobbilyking | WA | 4ms | 28628kb | C++17 | 7.9kb | 2024-02-04 01:52:25 | 2024-02-04 01:52:25 |
Judging History
answer
// wrong code, saving the normal centroid decomp code somewhere
//Centroid Decomposition
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef long double ld;
typedef pair<ll, ll> pl;
typedef vector<ll> vl;
#define G(x) ll x; cin >> x;
#define F(i, l, r) for(ll i = l; i < (r); ++i)
const int N = 200010;
#define FD(i, l, r) for (ll i = l; i > (r); --i)
#define K first
#define V second
#define GS(s) string s; cin >> s;
#define A(a) begin(a), end(a)
vector<pl> tree[N];
ll sz[N], cPar[N], lvl[N]; //lvl is 1-indexed
#define L 20
ll dep[N], par[N][L], distFromRoot[N];
ll tin[N], tout[N];
void dfs(ll i, ll p, ll pw) {
static int time = 0;
dep[i] = dep[p] + 1;
par[i][0] = p;
distFromRoot[i] = pw;
tin[i] = time++;
F(l, 1, L) {
par[i][l] = par[par[i][l - 1]][l - 1];
}
for(auto [j, w]: tree[i]) if(j - p) dfs(j, i, pw + w);
tout[i] = time;
}
ll lca(ll a, ll b) {
if(dep[a] < dep[b]) swap(a, b);
FD(l, L - 1, -1) if((dep[a] - dep[b]) >> l) a = par[a][l];
if(a == b) return a;
FD(l, L - 1, -1) if(par[a][l] - par[b][l]) a = par[a][l], b = par[b][l];
return par[a][0];
}
ll dist(ll a, ll b){
return distFromRoot[a] + distFromRoot[b] - 2 * distFromRoot[lca(a, b)];
}
typedef pl T;
typedef ll U;
// combining segtree nodes a and b
pl f(pl a, pl b) {
if (a.K == b.K) return min(a, b);
return max(a, b);
}
// applying updates a and b (in that order)
U g(U b, U a) { return a + b; }
// applying update b to segtree node a
T h(U b, T a) {
a.K += b;
return a;
}
struct lztree {
ll n;
T idT = {-1e18, -1};
vector<T> t;
U idU = 0;
vector<U> d;
void calc(ll p) { t[p] = h(d[p], f(t[p * 2], t[p * 2 + 1])); }
void apply(ll p, U v) {
t[p] = h(v, t[p]);
if(p < n) d[p] = g(v, d[p]);
}
void push(ll p) {
p += n;
FD(s, L, 0) {
ll i = p >> s;
if(d[i] != idU) {
apply(i * 2, d[i]);
apply(i * 2 + 1, d[i]);
d[i] = idU;
}
}
}
#define rein(p) lower_bound(A(mytins), p) - mytins.begin()
// difference between tshi: i reindexx before doing shit
// void modify(ll p, T v) {
// p = rein(p);
// push(p);
// t[p += n] = v;
// while(p > 1) calc(p /= 2);
// }
void modify(ll l, ll r, U v) {
l = rein(l), r = rein(r);
if (l >= r) return;
push(l), push(r - 1);
bool cl = false, cr = false;
for(l += n, r += n; l < r; l /= 2, r /= 2) {
if(cl) calc(l - 1);
if(cr) calc(r);
if(l & 1) apply(l++, v), cl = true;
if(r & 1) apply(--r, v), cr = true;
}
for(--l; r; l /= 2, r /= 2) {
if(cl) calc(l);
if(cr) calc(r);
}
}
T query(ll l, ll r) {
l = rein(l), r = rein(r);
if (l >= r) return idT;
push(l), push(r - 1);
T resl = idT, resr = idT;
for(l += n, r += n; l < r; l /= 2, r /= 2) {
if(l & 1) resl = f(resl, t[l++]);
if(r & 1) resr = f(t[--r], resr);
}
return f(resl, resr);
}
lztree() {}
// This lazy tree wants to effectively query tin/tout ranges.
// So reindex everything by tin; it is the responsibility of the passer to pass in correct tin/tout ranges.
// (point modifies pass in tin ranges)
vl mytins;
lztree(vector<pl> pts) {
assert(pts.size());
n = pts.size();
mytins.resize(n);
t.resize(2*n, idT);
d.resize(n, idU);
F(i, 0, pts.size()) {
mytins[i] = tin[pts[i].K];
t[i+n] = pl(pts[i].V, pts[i].K);
}
FD(i, n-1, -1) t[i] = f(t[i*2], t[i*2+1]);
}
};
struct distance_set {
// segtree of nodes, sorted by tin time
// this allows us to to range adds, range queries
// ll pointupd(ll node, ll x) {
// seg.modify(tin[node], x);
// }
void rangeupd(ll node, ll x) {
// cout << "FUCK " << node << " " << tin[node] << " " << tout[node] << endl;
seg.modify(tin[node], tout[node], x);
// add x to everybody's tin, tout time.
}
pl query(ll node = -1) {
if (node == -1); {
// cout << "WTF " << tin[1] << " " << tout[1] << endl;
// for (auto x: seg.mytins) cout << x << " "; cout << endl;
return seg.query(tin[1], tout[1]);
}
// else, exclude node's tin, tout from the answer.
return max(seg.query(tin[1], tin[node]), seg.query(tout[node], tout[1]));
}
distance_set() {}
lztree seg;
distance_set(vector<pl> things) : seg(things) {
}
};
distance_set children[N];
ll getSize(ll i, ll p) {
sz[i] = 1;
for(auto [j, _] : tree[i])
if(j - p && !lvl[j])
sz[i] += getSize(j, i);
return sz[i];
}
ll centroid(ll i, ll p, ll n) {
for(auto [j, _] : tree[i])
if(j - p && !lvl[j] && sz[j] > n / 2)
return centroid(j, i, n);
return i;
}
ll a[N];
void dfsToGetThings(vector<pl>& things, ll i, ll p, ll dist) {
things.emplace_back(i, dist - a[i]);
for (auto [j, x] : tree[i]) if (j-p && !lvl[j]) {
dfsToGetThings(things, j, i, x + dist);
}
}
ll decomp(ll i, ll l) {
vector<pl> things;
dfsToGetThings(things, i, -1, 0);
sort(A(things), [&](auto &a, auto &b) {
return tin[a.K] < tin[b.K];
});
assert(things.size());
// cout << "WTF??? " << things.size() << endl;
ll cent = centroid(i, -1, getSize(i, -1));
children[cent] = distance_set(things);
// cout << "FILLED UP" << i << "; " << cent << endl;
things.clear();
lvl[cent] = l;
for(auto [j, _]: tree[cent]) if(!lvl[j])
cPar[decomp(j, l + 1)] = cent;
return cent;
}
int main() {
// freopen("newbarn.in", "r", stdin);
// freopen("newbarn.out", "w", stdout);
ios_base::sync_with_stdio(0);
cin.tie(0);
G(n) G(q)
F(i, 1, n+1) cin >> a[i];
F(i, 2, n+1) {
G(x) G(y) tree[x].emplace_back(i, y);
tree[i].emplace_back(x, y);
}
dfs(1, 1, 0);
auto root = decomp(1, 0);
cPar[root] = 0;
// cout << "ROOT " << root << endl;
F(i, 1, n+1) cout << i << ": " << cPar[i] << endl;
F(i, 1, n+1) assert(children[i].seg.n);
// cout << "LOL? " << endl;
while (q--) {
G(x) G(y) G(w)
// recursively updating is easy
// cout << " rec update " << endl;
{
// Updating is wrong, we need to update all of its children's centroids too.. FUCKKK
// ll root = y;
// while (y) {
// // cout << "UDPATING " << y << " " << root << " " << w << endl;
// children[y].rangeupd(root, -w);
// // cout << "DONE UPD " << endl;
// y = cPar[y];
// }
F(i, 1, n+1) children[i].rangeupd(y, -w);
}
// cout << " do query idot " << endl;
assert(children[x].seg.n);
auto base = children[x].query();
cout << base.K << " ; " << base.V << endl;
assert(base.V != -1);
{
ll root = x;
ll income = x;
x = cPar[x];
while (x) {
base = f(base, h(dist(x, root), children[x].query(income)));
income = x;
x = cPar[x];
}
}
cout << base.V << " " << base.K << endl;
// cout << recrusivelyQuery(x, )
}
}
详细
Test #1:
score: 0
Wrong Answer
time: 4ms
memory: 28628kb
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:
1: 2 2: 3 3: 0 4: 5 5: 3 6: 5 100005 ; 6 6 100005 -1 ; 1 6 10 -1 ; 1 6 10 4 ; 1 1 4 -1 ; 1 1 -1 -73 ; 4 1 1
result:
wrong answer 1st lines differ - expected: '6 100005', found: '1: 2'