Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- typedef long double ld;
- typedef pair<int, int> pii;
- typedef pair<long long, long long> pll;
- #define ff first
- #define ss second
- #define mp make_pair
- #define pb push_back
- #define ub upper_bound
- #define lb lower_bound
- #define all(x) (x).begin(), (x).end()
- #define fap(x) cout << " -- " << #x << ": " << (x) << "\n"
- #define FastIO ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
- const long long INF = 2000000000000000000LL; // 2e18
- const int inf = 0x3f3f3f3f;
- const long double EPS = 1e-9;
- namespace seg {
- // point update, range query maximum
- const int N = 10000+7;
- ll tr[4*N];
- void build() {
- memset(tr, 0, sizeof tr);
- }
- // adds x in point p
- void update(int at, int l, int r, int p, ll x) {
- if(l == r) {
- tr[at] = x;
- return ;
- }
- int lc = at+at, rc = lc+1, mid = (l+r)/2;
- if(p <= mid) update(lc, l, mid, p, x);
- else update(rc, mid+1, r, p, x);
- tr[at] = max(tr[lc], tr[rc]);
- }
- // returns the maximum in lo-hi range
- ll query(int at, int l, int r, int lo, int hi) {
- if(l > hi or r < lo) return -INF; // minimum value, change accordingly
- if(l >= lo and r <= hi) return tr[at];
- int lc = at+at, rc = lc+1, mid = (l+r)/2;
- return max(query(lc, l, mid, lo, hi), query(rc, mid+1, r, lo, hi));
- }
- };
- /**
- * Heavy Light Decomposition
- * Build Complexity O(n)
- * Query Complexity O(lg^2 n)
- * Call init() with number of nodes
- * It's probably for the best to not do "using namespace hld"
- **/
- namespace hld {
- /**
- * N is the maximum number of nodes
- * g is the adjacency graph
- * par, lev, size corresponds to parent, depth, subtree-size
- * head[u] is the starting node of the chain u is in
- * in[u] to out[u] keeps the subtree indices
- **/
- const int N = 10000+7;
- vector<int> g[N];
- int par[N], lev[N], head[N], size[N], in[N], out[N];
- int cur_pos, n;
- /**
- * returns the size of subtree rooted at u
- * maintains the child with the largest subtree at the front of g[u]
- **/
- int dfs(int u, int p) {
- int sz = 1;
- for(auto &v : g[u]) {
- if(v == p) continue;
- sz += dfs(v, u);
- if(size[v] > size[g[u].front()]) {
- swap(v, g[u].front());
- }
- }
- par[u] = p;
- lev[u] = lev[p] + 1;
- return size[u] = sz;
- }
- /**
- * decomposed the tree in an array
- * note that there is no physical array here
- **/
- void decompose(int u, int p) {
- in[u] = ++cur_pos;
- for(auto &v : g[u]) {
- if(v == p) continue;
- head[v] = (v == g[u].front() ? head[u] : v);
- decompose(v, u);
- }
- out[u] = cur_pos;
- }
- /**
- * initializes the structure with _n nodes
- **/
- void init(int _n) {
- n = _n;
- cur_pos = 0;
- dfs(1, 0);
- head[1] = 1;
- decompose(1, 0);
- }
- /**
- * checks whether p is an ancestor of u
- **/
- bool isances(int p, int u) {
- return in[p] <= in[u] and out[u] <= out[p];
- }
- /**
- * Returns the maximum node value in the path u - v
- **/
- ll query(int u, int v) {
- ll ret = -INF;
- const int LIM = 4000;
- int cnt = 0;
- while(!isances(head[u], v)) {
- ret = max(ret, seg::query(1, 1, n, in[head[u]], in[u]));
- u = par[head[u]];
- assert(++cnt < LIM);
- }
- swap(u, v);
- cnt = 0;
- while(!isances(head[u], v)) {
- ret = max(ret, seg::query(1, 1, n, in[head[u]], in[u]));
- u = par[head[u]];
- assert(++cnt < LIM);
- }
- if(in[v] < in[u]) swap(u, v);
- ret = max(ret, seg::query(1, 1, n, in[u]+1, in[v]));
- return ret;
- }
- /**
- * Assigns val to node u
- **/
- void update(int u, ll val) {
- seg::update(1, 1, n, in[u], val);
- }
- };
- int main() {
- FastIO;
- int t, tc=0;
- cin >> t;
- while(t--) {
- int n;
- cin >> n;
- vector< vector<int> > edg;
- for(int i=1; i<n; ++i) {
- int u, v, w;
- cin >> u >> v >> w;
- edg.push_back({u, v, w});
- hld::g[u].push_back(v);
- hld::g[v].push_back(u);
- }
- hld::init(n);
- seg::build();
- for(auto &e : edg) {
- if(e[1] == hld::par[e[0]]) swap(e[0], e[1]);
- hld::update(e[1], e[2]);
- }
- string op;
- while(cin >> op) {
- if(op == "QUERY") {
- int u, v;
- cin >> u >> v;
- cout << hld::query(u, v) << "\n";
- }
- else if(op == "CHANGE") {
- int p, w;
- cin >> p >> w;
- hld::update(edg[--p][1], w);
- }
- else break;
- }
- for(int i=1; i<=n; ++i) hld::g[i].clear();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement