【luogu P4114 Qtree1】 題解
阿新 • • 發佈:2018-08-04
\n oid new update left www. esp href int
題目鏈接:https://www.luogu.org/problemnew/show/P4114
1.把邊權轉化到點權:選取連接這條邊的兩個點中較深的一個。
2.查詢點到點之間的邊權時,要從seg[x]+1 到 seg[y],因為seg[x]其實連接的是上面一條邊的邊權。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define ll long long #define lson left, mid, rt<<1 #define rson mid + 1, right, rt<<1|1 using namespace std; const ll maxn = 300000 + 10; char opt[9]; ll n, m, root, res; ll top[maxn], rev[maxn], seg[maxn], son[maxn]; ll fa[maxn], size[maxn], deep[maxn]; ll u[maxn], v[maxn], w[maxn]; ll tree[maxn<<2], lazy[maxn<<2], num, node[maxn]; struct edge{ ll next, from, to, len; }e[maxn<<2]; ll head[maxn], cnt; void add(ll u, ll v, ll w) { e[++cnt].from = u; e[cnt].len = w; e[cnt].next = head[u]; e[cnt].to = v; head[u] = cnt; } //-----segment_tree----- void PushUP(ll rt) { tree[rt] = max(tree[rt<<1], tree[rt<<1|1]); } void build(ll left, ll right, ll rt) { if(left == right) { tree[rt] = rev[left]; return; } ll mid = (left + right)>>1; build(lson); build(rson); PushUP(rt); } void PushDOWN(ll rt) { lazy[rt<<1] = lazy[rt]; lazy[rt<<1|1] = lazy[rt]; tree[rt<<1] = lazy[rt]; tree[rt<<1|1] = lazy[rt]; lazy[rt] = 0; } void update(ll l, ll r, ll add, ll left, ll right, ll rt) { if(l <= left && r >= right) { tree[rt] = add; lazy[rt] = add; return; } ll mid = (left + right)>>1; if(lazy[rt]) PushDOWN(rt); if(l <= mid) update(l, r, add, lson); if(r > mid) update(l, r, add, rson); PushUP(rt); } ll query(ll l, ll r, ll left, ll right, ll rt) { ll res = -0x7fffffff; if(l <= left && r >= right) { return tree[rt]; } ll mid = (left + right)>>1; if(lazy[rt]) PushDOWN(rt); if(l <= mid) res = max(res, query(l, r, lson)); if(r > mid) res = max(res, query(l, r, rson)); return res; } //---------------------- void dfs1(ll u, ll f, ll d) { ll maxson = -1; size[u] = 1; deep[u] = d; fa[u] = f; for(ll i = head[u]; i != -1; i = e[i].next) { ll v = e[i].to; if(f != v) { dfs1(v, u, d+1); size[u] += size[v]; if(size[v] > maxson) son[u] = v, maxson = size[v]; } } } void dfs2(ll u, ll t) { seg[u] = ++num; rev[num] = node[u]; top[u] = t; if(!son[u]) return; dfs2(son[u], t); for(ll i = head[u]; i != -1; i = e[i].next) { ll v = e[i].to; if(v == son[u] || v == fa[u]) continue; dfs2(v,v); } } void updRange(ll x, ll y, ll k) { while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x, y); update(seg[top[x]], seg[x], k, 1, n, 1); x = fa[top[x]]; } if(deep[x] > deep[y]) swap(x, y); update(seg[x], seg[y], k, 1, n, 1); } ll qRange(ll x, ll y) { ll ans = 0; while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x, y); res = 0; res = query(seg[top[x]], seg[x], 1, n, 1); ans = max(res, ans); x = fa[top[x]]; } if(deep[x] > deep[y]) swap(x, y); res = 0; res = query(seg[x]+1, seg[y], 1, n, 1); ans = max(res, ans); return ans; } int main() { memset(head, -1, sizeof(head)); scanf("%lld",&n); root = 1; for(ll i = 1; i < n; i++) { scanf("%lld%lld%lld",&u[i],&v[i],&w[i]); add(u[i],v[i],w[i]); add(v[i],u[i],w[i]); } dfs1(root, 0, 1); //for(int i = 1; i <= n; i++) cout<<deep[i]<<" "; for(ll i = 1; i < n; i++) { if(deep[u[i]] < deep[v[i]]) node[v[i]] = w[i]; else node[u[i]] = w[i]; } //for(int i = 1; i <= n; i++) cout<<node[i]<<" "; dfs2(root, root); build(1, n, 1); while(cin>>opt && opt[0] != 'D') { ll x, y, z; if(opt[0] == 'C') { scanf("%lld%lld",&x,&y); if(deep[u[x]] > deep[v[x]]) updRange(u[x], u[x], y); else updRange(v[x], v[x], y); } else { scanf("%lld%lld",&x,&y); if(x == y) { printf("0\n"); continue; } printf("%lld\n",qRange(x,y)); } } }
【luogu P4114 Qtree1】 題解