題意很裸,調了好久,,最後發現push_up寫錯了,, splay功底還是不夠, 再刷一波splay...
#include <bits/stdc++.h>
using namespace std;
int n,m;
const int MAXN = 310010;
const int INF = 0x3f3f3f3f;
struct Node *null;
struct Node{
Node * fa, *ch[2];
int val, MAX;
int rev, add;
inline void clear(){
val = 0;
MAX = -INF;
rev = add = 0;
fa = ch[0] = ch[1] = null;
}
inline void push_up(){
MAX = max(val, max(ch[0]->MAX, ch[1]->MAX));
}
inline void update_add(int w){
if(this == null) return;
val += w;
add += w;
MAX += w;
}
inline void push_down(){
if(add){
ch[0]->update_add(add);
ch[1]->update_add(add);
add = 0;
}
if(rev){
ch[0]->flip();
ch[1]->flip();
rev = 0;
}
}
inline bool d(){
return fa->ch[1] == this;
}
inline void setc(Node *p, int d){
ch[d] = p;
p->fa = this;
}
inline bool isroot(){
return fa==null||fa->ch[0]!=this&&fa->ch[1]!=this;
}
inline void rot(){
Node *f = fa, *ff = fa->fa;
bool c = d(), cc = fa->d();
f->setc(ch[!c], c);
this->setc(f, !c);
if(ff->ch[cc] == f) ff->setc(this, cc);
else this->fa = ff;
f->push_up();
}
inline void go(){
if(!isroot()) fa->go();
push_down();
}
inline Node *splay(){
go();
while(!isroot()){
rot();
}
push_up();
return this;
}
inline Node *access(){
for(Node *q=this,*p=null; q!=null; p=q,q=q->fa){
q->splay()->setc(p, 1);
q->push_up();
}
return splay();
}
inline void flip(){
if(this == null) return;
swap(ch[0], ch[1]);
rev ^= 1;
}
inline void make_root(){
access()->flip();
}
inline Node *find_root(){
Node *x;
for(x=access();x->push_down(),x->ch[0]!=null;x = x->ch[0]);
return x;
}
inline void cut(){
access();
ch[0]->fa = null;
ch[0] = null;
push_up();
}
inline void cut(Node *x){
x->make_root();
cut();
}
inline void link(Node *x){
make_root();
fa = x;
}
};
Node poor[MAXN];
Node *tail;
Node *node[MAXN];
void init(int n){
tail = poor;
null = tail++;
null->clear();
for(int i=1; i<=n; i++){
node[i] = tail++;
node[i]->clear();
}
}
struct Edge{
int to,next;
}edge[MAXN*2];
int tot,head[MAXN];
void add_edge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u, int pre){
for(int i=head[u]; ~i; i=edge[i].next){
int v = edge[i].to;
if(v == pre) continue;
dfs(v, u);
node[v]->fa = node[u];
}
}
void ADD(Node *x, Node *y, int w){
x->access();
for(x=null; y!=null; x=y,y=y->fa){
y->splay();
if(y->fa == null){
y->ch[1]->update_add(w);
x->update_add(w);
y->val += w;
y->push_up();
return;
}
y->setc(x, 1);
y->push_up();
}
}
int ask(Node *x, Node *y){
x->access();
for(x=null;y!=null;x=y,y=y->fa){
y->splay();
if(y->fa == null){
return max(y->val, max(y->ch[1]->MAX, x->MAX));
}
y->setc(x, 1);
y->push_up();
}
}
int main(){
while(cin>>n){
tot = 0;memset(head, -1, sizeof(head));
for(int i=1; i<n; i++){
int u,v,w;
scanf("%d %d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
init(n);
dfs(1, 1);
for(int i=1; i<=n;i ++){
int t;
scanf("%d", &t);
node[i]->val = t;
}
cin>>m;
while(m--){
int cmd, x, y,z;
scanf("%d", &cmd);
if(cmd == 1){
scanf("%d %d",&x, &y);
if(node[x]->find_root() == node[y]->find_root())
{
cout<<-1<<endl;
continue;
}
node[x]->link(node[y]);
}
else if(cmd == 2){
scanf("%d %d",&x, &y);
if(x==y||node[x]->find_root() != node[y]->find_root())
{
cout<<-1<<endl;
continue;
}
node[y]->cut(node[x]);
}
else if(cmd == 3){
scanf("%d %d %d", &x, &y, &z);
if(node[y]->find_root() != node[z]->find_root())
{
cout<<-1<<endl;
continue;
}
ADD(node[y], node[z], x);
}
else {
scanf("%d %d", &x, &y);
if(node[x]->find_root() != node[y]->find_root())
{
cout<<-1<<endl;
continue;
}
printf("%d\n", ask(node[x], node[y]));
}
}
cout<<endl;
}
return 0;
}