题解:
考场上刚T2导致这道题没写。。。 其实挺傻逼的。
LCT的时候维护一个2*2的矩阵就行了,顺便维护一下虚子树的信息,时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(LL x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+'0');
}
const int N=1e5+50;
const LL inf=1e13;
int n,m,pv[N],fa[N];
vector <int> edge[N];
struct mat {
LL a[2][2];
mat(LL v=0) {a[0][0]=a[0][1]=a[1][0]=a[1][1]=v;}
friend inline mat operator *(const mat &a,const mat &b) {
mat c(inf);
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
c.a[i][k]=min(c.a[i][k],a.a[i][j]+b.a[j][k]);
return c;
}
};
struct node {
node *lc,*rc,*fa;
LL f[2];
mat a;
node() : lc(NULL),rc(NULL),fa(NULL) {}
inline void upt() {
a.a[1][0]=a.a[1][1]=f[1];
a.a[0][1]=f[0];
a.a[0][0]=inf;
if(rc) a=a*rc->a;
if(lc) a=lc->a*a;
}
} *pos[N],Pool[N],*pool=Pool;
inline void add(node *x,node *y,int t) {
LL sg=min(y->a.a[1][0],y->a.a[1][1]);
LL sf=min(sg,min(y->a.a[0][0],y->a.a[0][1]));
x->f[0]+=sg*t; x->f[1]+=sf*t;
}
inline void pre(int x,int f) {
fa[x]=f;
node *p=pos[x]=++pool;
p->f[1]=pv[x]; p->f[0]=0;
for(auto v:edge[x])
if(v^f) pre(v,x);
p->upt();
if(f) add(pos[f],p,1), p->fa=pos[f];
}
inline bool isroot(node *x) {return (!x->fa) || (x->fa->lc!=x && x->fa->rc!=x);}
inline bool which(node *x) {return (x->fa->lc)==x;}
inline void rotate(node *x) {
node *y=x->fa, *z=y->fa;
if(!isroot(y)) ((z->lc==y) ? z->lc : z->rc)=x;
y->fa=x; x->fa=z;
if(y->lc==x) {
node *b=x->rc;
if(b) b->fa=y;
y->lc=b; x->rc=y;
} else {
node *b=x->lc;
if(b) b->fa=y;
y->rc=b; x->lc=y;
} y->upt(); x->upt();
}
inline void splay(node *x) {
while(!isroot(x)) {
node *y=x->fa;
if(!isroot(y)) {
if(which(x)==which(y)) rotate(y);
else rotate(x);
} rotate(x);
}
}
inline void access(node *x) {
for(node *y=NULL;x;y=x,x=x->fa) {
splay(x);
if(x->rc) add(x,x->rc,1);
x->rc=y;
if(x->rc) add(x,x->rc,-1);
x->upt();
}
}
inline void add_lim(int x,int a,LL val) {
node *p=pos[x];
access(p);
splay(p);
p->f[a]+=val; p->upt();
}
int main() {
n=rd(), m=rd(); rd();
for(int i=1;i<=n;i++) pv[i]=rd();
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
edge[x].push_back(y);
edge[y].push_back(x);
} pre(1,0);
for(int i=1;i<=m;i++) {
int x=rd(), a=rd();
int y=rd(), b=rd();
add_lim(x,a^1,inf);
add_lim(y,b^1,inf);
splay(pos[1]);
LL ans=min(pos[1]->a.a[0][0],pos[1]->a.a[0][1]);
ans=min(ans,min(pos[1]->a.a[1][0],pos[1]->a.a[1][1]));
add_lim(x,a^1,-inf);
add_lim(y,b^1,-inf);
ans=(ans>=inf) ? -1 : ans;
W(ans), putchar('\n');
}
}