#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
#define LL long long
#define eps 1e-8
#define MP make_pair
#define N 300020
#define M 600020
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define mod 258280327
#define inf 0x3f3f3f3f
#define ULL unsigned long long
int readint() {
char c;
while((c = getchar()) && !(c >= '0' && c <= '9'));
int ret = c - '0';
while((c = getchar()) && c >= '0' && c <= '9')
ret = ret * 10 + c - '0';
return ret;
}
int fst[N], nxt[M], to[M], e;
int tot, pre[N], ch[N][2], key[N];
int add[N], rev[N], mx[N];
bool rt[N];
int n, m;
void init() {
memset(fst, -1, sizeof fst);
memset(ch, 0, sizeof ch);
memset(pre, 0, sizeof pre);
memset(rev, 0, sizeof rev);
memset(add, 0, sizeof add);
memset(rt, 1, sizeof rt);
e = 0;
}
void add_edge(int u, int v) {
to[e] = v, nxt[e] = fst[u], fst[u] = e++;
}
void dfs(int u, int p) {
pre[u] = p;
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = to[i];
if(v != p)
dfs(v, u);
}
}
bool judge(int u, int v) {
while(pre[u]) u = pre[u];
while(pre[v]) v = pre[v];
return u == v;
}
void push_up(int x) {
mx[x] = max(mx[ch[x][0]], mx[ch[x][1]]);
mx[x] = max(mx[x], key[x]);
}
void update_add(int x, int val) {
if(!x) return;
key[x] += val;
add[x] += val;
mx[x] += val;
}
void update_rev(int x) {
if(!x) return;
swap(ch[x][0], ch[x][1]);
rev[x] ^= 1;
}
void push_down(int x) {
if(add[x]) {
update_add(ch[x][0], add[x]);
update_add(ch[x][1], add[x]);
add[x] = 0;
}
if(rev[x]) {
update_rev(ch[x][0]);
update_rev(ch[x][1]);
rev[x] = 0;
}
}
void P(int x) {
if(!rt[x]) P(pre[x]);
push_down(x);
}
void rot(int x) {
int y = pre[x], d = ch[y][1] == x;
ch[y][d] = ch[x][!d];
pre[ch[x][!d]] = y;
pre[x] = pre[y];
pre[y] = x;
ch[x][!d] = y;
if(rt[y])
rt[y] = false, rt[x] = true;
else
ch[pre[x]][ch[pre[x]][1]==y] = x;
push_up(y);
}
void splay(int x) {
P(x);
while(!rt[x]) {
int f = pre[x], ff = pre[f];
if(rt[f])
rot(x);
else if((ch[ff][1] == f) == (ch[f][1] == x))
rot(f), rot(x);
else
rot(x), rot(x);
}
push_up(x);
}
// return the root of x
int Access(int x) {
int y = 0;
for(; x; y = x, x = pre[x]) {
splay(x);
rt[ch[x][1]] = true;
ch[x][1] = y;
rt[y] = false;
push_up(x);
}
return y;
}
void make_root(int u) {
Access(u);
splay(u);
update_rev(u);
}
void link(int u, int v) {
if(judge(u, v)) {
puts("-1");
return;
}
make_root(u);
pre[u] = v;
}
void cut(int u, int v) {
if(u == v || !judge(u, v)) {
puts("-1");
return;
}
make_root(u);
splay(v);
pre[ch[v][0]] = pre[v];
pre[v] = 0;
rt[ch[v][0]] = true;
ch[v][0] = 0;
push_up(v);
}
//调用后u是原来u和v的lca,v和ch[u][1]分别存着lca的2个儿子
//(原来u和v所在的2颗子树)
void lca(int &u, int &v) {
Access(v), v = 0;
for(splay(u); pre[u]; v = u, u = pre[u], splay(u)) {
rt[ch[u][1]] = true;
ch[u][1] = v;
rt[v] = false;
push_up(u);
}
}
void update(int u, int v, int w) {
if(!judge(u, v)) {
puts("-1");
return;
}
lca(u, v);
update_add(ch[u][1], w);
update_add(v, w);
key[u] += w;
push_up(u);
}
void query(int u, int v) {
if(!judge(u, v)) {
puts("-1");
return;
}
lca(u, v);
printf("%d\n", max(max(mx[ch[u][1]], mx[v]), key[u]));
}
int main() {
while(scanf("%d", &n) != -1) {
init();
for(int i = 1; i < n; ++i) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
mx[0] = -inf;
for(int i = 1; i <= n; ++i) {
scanf("%d", &key[i]);
mx[i] = key[i];
}
dfs(1, 0);
scanf("%d", &m);
while(m--) {
int u, v, w, op;
scanf("%d", &op);
if(op == 3) scanf("%d", &w);
scanf("%d%d", &u, &v);
if(op == 1) {
link(u, v);
}
if(op == 2) {
cut(u, v);
}
if(op == 3) update(u, v, w);
if(op == 4) query(u, v);
}
puts("");
}
return 0;
}
hdu 4010 Query on The Trees (lct模板)
最新推荐文章于 2019-09-19 01:14:54 发布