直接裸上动态dp即可,因为某些不知道的原因NOIP能过,别的地方不开O2都过不了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define gc getchar()
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
char Type[10];
const int N=100010;
struct edges{
int to,pre;
}e[N<<1];int p[N],qa[N],qb[N],qx[N],qy[N],h[N],etop;
inline int add_edge(int u,int v)
{
return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
namespace subtask1{
const int N=2010;const lint INF=100000000000ll;
int mst[N],mstx[N];lint f[N][2];
int dfs(int x,int fa=0)
{
f[x][0]=0,f[x][1]=p[x];
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa)
{
dfs(y,x);
f[x][0]+=f[y][1];
f[x][1]+=min(f[y][0],f[y][1]);
}
f[x][0]=min(f[x][0],INF),
f[x][1]=min(f[x][1],INF);
if(mst[x]) f[x][mstx[x]^1]=INF;
return 0;
}
inline int brute_force_nm(int n,int m)
{
rep(i,1,m)
{
int a=qa[i],b=qb[i],x=qx[i],y=qy[i];
mst[a]=mst[b]=1,mstx[a]=x,mstx[b]=y;
dfs(1);
lint Ans=min(f[1][0],f[1][1]);
if(Ans<INF) printf("%lld\n",Ans);
else printf("-1\n");
mst[a]=mst[b]=0;
}
return n-n+0;
}
}
namespace subtask_std{
const lint INF=100000000000;
struct node{
int ept;lint w[3][3];
inline node operator+(const node &n)const
{
node ans;rep(i,0,1) rep(j,0,1) ans.w[i][j]=INF;
if(ept) ans=n;if(n.ept) ans=*this;ans.ept=0;
if(ept||n.ept) return ans;
rep(i,0,1) rep(j,0,1) rep(k,0,1) rep(t,0,1)
if(k+t>=1) ans.w[i][j]=min(ans.w[i][j],w[i][k]+n.w[t][j]);
return ans;
}
inline node operator+=(const node &n)
{ return (*this)=(*this)+n; }
inline lint f()const { return min(w[1][0],w[1][1]); }
inline lint g()const { return min(w[0][0],w[0][1]); }
inline lint ans()const { return min(f(),g()); }
}ans;
struct segment{
int l,r;
segment *ch[2];
node v;
}*rt;
lint g[N],f[N],fs[N],gs[N];int tms[N],dfc;
int in[N],out[N],top[N],bot[N],d[N],fa[N],sz[N],son[N];
inline int push_up(segment* &rt)
{
return rt->v=rt->ch[0]->v+rt->ch[1]->v,0;
}
int build(segment* &rt,int l,int r)
{
rt=new segment,rt->l=l,rt->r=r;
if(l==r)
{
rt->v.w[0][1]=rt->v.w[1][0]=INF,
rt->v.w[0][0]=g[tms[l]],rt->v.w[1][1]=f[tms[l]];
return 0;
}
int mid=(l+r)>>1;
build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
return push_up(rt);
}
int update(segment* &rt,int p,lint f,lint g)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(l==r)
{
rt->v.w[0][1]=rt->v.w[1][0]=INF,
rt->v.w[0][0]=g,rt->v.w[1][1]=f;
return 0;
}
update(rt->ch[p>mid],p,f,g);return push_up(rt);
}
int query(segment* &rt,int s,int t)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return ans+=rt->v,0;
if(s<=mid) query(rt->ch[0],s,t);
if(mid<t) query(rt->ch[1],s,t);
return 0;
}
int fir_dfs(int x)
{
d[x]=d[fa[x]]+1;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa[x])
{
fa[y]=x,fir_dfs(y),sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
return ++sz[x];
}
int sec_dfs(int x)
{
in[x]=++dfc,tms[dfc]=x;
if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]),bot[x]=son[x][bot];
else bot[x]=x;
f[x]=p[x],g[x]=0;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)!=fa[x]&&e[i].to!=son[x])
{
top[y]=y,sec_dfs(y);
f[x]+=min(gs[y],fs[y]);
g[x]+=fs[y];
}
if(son[x]) fs[x]=f[x]+min(fs[son[x]],gs[son[x]]),gs[x]=g[x]+fs[son[x]];
else fs[x]=f[x],gs[x]=g[x];
out[x]=dfc;return 0;
}
inline int qry(int x) { ans.ept=1,query(rt,in[x],in[bot[x]]);return 0; }
int lst[N];
inline int upd(int x,int v)
{
int cnt=0;
for(int y=top[x],z=fa[y];z;y=top[z],z=fa[y])
lst[++cnt]=y;
for(int i=cnt,y,z;i;i--)
y=lst[i],z=fa[y],qry(y),
update(rt,in[z],f[z]-=ans.ans(),g[z]-=ans.f());
if(v) update(rt,in[x],f[x],g[x]=INF);
else update(rt,in[x],f[x]=INF,g[x]);
for(int i=1,y,z;i<=cnt;i++)
y=lst[i],z=fa[y],qry(y),
update(rt,in[z],f[z]+=ans.ans(),g[z]+=ans.f());
return 0;
}
lint tf[N],tg[N];
inline int back(int x)
{
update(rt,in[x],f[x]=tf[x],g[x]=tg[x]);
for(int y=top[x],z=fa[y];z;y=top[z],z=fa[y])
update(rt,in[z],f[z]=tf[z],g[z]=tg[z]);
return 0;
}
inline int acceptable_solution(int n,int m)
{
fir_dfs(1),top[1]=1,sec_dfs(1);
rep(i,1,n) tf[i]=f[i],tg[i]=g[i];
build(rt,1,n);
rep(i,1,m)
{
upd(qa[i],qx[i]),
upd(qb[i],qy[i]);
qry(1);
if(ans.ans()<INF) printf("%lld\n",ans.ans());
else printf("-1\n");
back(qa[i]),back(qb[i]);
}
return 0;
}
}
int main()
{
int n=inn(),m=inn(),x,y;scanf("%s",Type);
rep(i,1,n) p[i]=inn();
rep(i,1,n-1) x=inn(),y=inn(),add_edge(x,y),add_edge(y,x);
rep(i,1,m) qa[i]=inn(),qx[i]=inn(),qb[i]=inn(),qy[i]=inn();
if(n<=2000&&m<=2000) return subtask1::brute_force_nm(n,m);
return subtask_std::acceptable_solution(n,m);
return 0;
}