题意:给定一个棵树,有四种操作,
1 连接两棵树,
2 把两棵树分开,
3 给 a 到 b 路径上的每个点加一个权值 w,
4 询问 a 到 b 的最大值。
析:最大值,很明显是要维护的,然后用就是一个裸板动态树。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 300000 + 10;
const int mod = 1000;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r > 0 && r <= n && c > 0 && c <= m;
}
int ch[maxn][2], pre[maxn], key[maxn];
int addv[maxn], rev[maxn], maxv[maxn];
bool is_rt[maxn];
void update_add(int rt, int d){
if(!rt) return ;
key[rt] += d;
addv[rt] += d;
maxv[rt] += d;
}
void update_rev(int rt){
if(!rt) return ;
swap(ch[rt][0], ch[rt][1]);
rev[rt] ^= 1;
}
void push_down(int rt){
if(addv[rt]){
update_add(ch[rt][0], addv[rt]);
update_add(ch[rt][1], addv[rt]);
addv[rt] = 0;
}
if(rev[rt]){
update_rev(ch[rt][0]);
update_rev(ch[rt][1]);
rev[rt] = 0;
}
}
void push_up(int rt){
maxv[rt] = max(maxv[ch[rt][0]], max(maxv[ch[rt][1]], key[rt]));
}
void rotate(int x){
int y = pre[x], kind = ch[y][1] == x;
ch[y][kind] = ch[x][!kind];
pre[ch[y][kind]] = y;
pre[x] = pre[y];
pre[y] = x;
ch[x][!kind] = y;
if(is_rt[y]) is_rt[y] = 0, is_rt[x] = 1;
else ch[pre[x]][ch[pre[x]][1]==y] = x;
pu(y);
}
void PP(int rt){
if(!is_rt[rt]) PP(pre[rt]);
pd(rt);
}
void splay(int rt){
PP(rt);
while(!is_rt[rt]){
int f = pre[rt], ff = pre[f];
if(is_rt[f]) rotate(rt);
else if((ch[ff][1]==f) == (ch[f][1]==rt)) rotate(f), rotate(rt);
else rotate(rt), rotate(rt);
}
pu(rt);
}
int access(int x){
int y = 0;
for( ; x; x = pre[y=x]){
splay(x);
is_rt[ch[x][1]] = 1, is_rt[ch[x][1]=y] = 0;
pu(x);
}
return y;
}
bool judge(int u, int v){
while(pre[u]) u = pre[u];
while(pre[v]) v = pre[v];
return u == v;
}
void mroot(int rt){
access(rt);
splay(rt);
update_rev(rt);
}
void lca(int &u, int &v){
access(v), v = 0;
while(u){
splay(u);
if(!pre[u]) return ;
is_rt[ch[u][1]] = 1;
is_rt[ch[u][1]=v] = 0;
pu(u);
u = pre[v = u];
}
}
void link(int u, int v){
if(judge(u, v)){
puts("-1");
return ;
}
mroot(u);
pre[u] = v;
}
void cut(int u, int v){-
if(u == v || !judge(u, v)){
puts("-1");
return ;
}
mroot(u);
splay(v);
pre[ch[v][0]] = pre[v];
pre[v] = 0;
is_rt[ch[v][0]] = 1;
ch[v][0] = 0;
pu(v);
}
void add(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;
pu(u);
}
void query(int u, int v){
if(!judge(u, v)){
puts("-1");
return ;
}
lca(u, v);
printf("%d
", max(maxv[v], max(maxv[ch[u][1]], key[u])));
}
struct Edge{
int to, next;
};
Edge edge[maxn<<1];
int head[maxn], cnt;
void addEdge(int u, int v){
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u){
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(pre[v]) continue;
pre[v] = u;
dfs(v);
}
}
int main(){
while(scanf("%d", &n) == 1){
cnt = 0;
for(int i = 0; i <= n; ++i){
is_rt[i] = 1; head[i] = -1;
ch[i][0] = ch[i][1] = 0;
pre[i] = rev[i] = 0;
addv[i] = 0;
}
for(int i = 1; i < n; ++i){
int u, v;
scanf("%d %d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
maxv[0] = -INF;
for(int i = 1; i <= n; ++i){
scanf("%d", key+i);
maxv[i] = key[i];
}
pre[1] = -1;
dfs(1);
pre[1] = 0;
scanf("%d", &m);
int op, x, y;
while(m--){
scanf("%d", &op);
if(op == 3){
int w;
scanf("%d %d %d", &w, &x, &y);
add(x, y, w);
}
else{
scanf("%d %d", &x, &y);
if(op == 1) link(x, y);
else if(op == 2) cut(x, y);
else query(x, y);
}
}
printf("
");
}
return 0;
}