分析:
听说是动态Dp的板题,但去年太菜没去冬令营听
仔细想想,用树链剖分也能过,而且的确也不是很难。
每个点有两种代价:选的代价和不选的代价。
线段树维护tree(x,0/1,0/1)分别表示左右端点是否选中。
合并两个线段:
其实就是分类讨论一下。。
然后保证先处理下层再处理上层,换言之,把每条链的信息反馈到其父亲节点上。
然后就简单了,每次限制,就把它对偶的选择代价+INF即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
#define INF 20000000000ll
using namespace std;
typedef long long ll;
vector<int> a[MAXN];
ll val[MAXN];
int n,m,son[MAXN],siz[MAXN],rnk[MAXN];
void dfs(int x,int f=0){
siz[x]=1;
son[x]=-1;
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==f)
continue;
dfs(u,x);
siz[x]+=siz[u];
if(son[x]==-1||siz[u]>siz[son[x]])
son[x]=u;
}
}
int dfn[MAXN],lft[MAXN],rft[MAXN],cnt,tot;
ll tree[MAXN*4][2][2];
int pl[MAXN*4],pr[MAXN*4],fa[MAXN],rt[MAXN];
ll val0[MAXN],val1[MAXN];
void build(int l,int r,int id){
if(l==r){
tree[id][0][0]=val0[rnk[l]];
tree[id][1][1]=val1[rnk[l]];
tree[id][0][1]=tree[id][1][0]=INF;
return ;
}
int mid=(l+r)>>1;
pl[id]=++tot;
pr[id]=++tot;
build(l,mid,pl[id]);
build(mid+1,r,pr[id]);
tree[id][0][0]=min(tree[pl[id]][0][1]+min(tree[pr[id]][0][0],tree[pr[id]][1][0]),tree[pr[id]][1][0]+min(tree[pl[id]][0][0],tree[pl[id]][0][1]));
tree[id][0][1]=min(tree[pl[id]][0][1]+min(tree[pr[id]][0][1],tree[pr[id]][1][1]),tree[pr[id]][1][1]+min(tree[pl[id]][0][0],tree[pl[id]][0][1]));
tree[id][1][0]=min(tree[pl[id]][1][1]+min(tree[pr[id]][0][0],tree[pr[id]][1][0]),tree[pr[id]][1][0]+min(tree[pl[id]][1][0],tree[pl[id]][1][1]));
tree[id][1][1]=min(tree[pl[id]][1][1]+min(tree[pr[id]][0][1],tree[pr[id]][1][1]),tree[pr[id]][1][1]+min(tree[pl[id]][1][0],tree[pl[id]][1][1]));
// PF("[%d %d %lld %lld %lld %lld]\n",l,r,tree[id][0][0],tree[id][0][1],tree[id][1][0],tree[id][1][1]);
}
void prepare(int x,int tp,int f=0){
dfn[x]=++cnt;
rnk[cnt]=x;
lft[x]=tp;
fa[x]=f;
if(son[x]==-1){
rft[x]=x;
if(tp==x){
rt[x]=++tot;
build(dfn[x],dfn[rft[x]],rt[x]);
val0[f]+=min(tree[rt[x]][1][0],tree[rt[x]][1][1]);
val1[f]+=min(min(tree[rt[x]][1][0],tree[rt[x]][1][1]),min(tree[rt[x]][0][0],tree[rt[x]][0][1]));
}
return ;
}
prepare(son[x],tp,x);
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==f||u==son[x])
continue;
prepare(u,u,x);
}
rft[x]=rft[son[x]];
if(x==tp){
rt[x]=++tot;
build(dfn[x],dfn[rft[x]],rt[x]);
val0[f]+=min(tree[rt[x]][1][0],tree[rt[x]][1][1]);
val1[f]+=min(min(tree[rt[x]][1][0],tree[rt[x]][1][1]),min(tree[rt[x]][0][0],tree[rt[x]][0][1]));
}
}
void change(int l,int r,int id,int pos){
if(l==r){
tree[id][0][0]=val0[rnk[l]];
tree[id][1][1]=val1[rnk[l]];
tree[id][0][1]=tree[id][1][0]=INF;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)
change(l,mid,pl[id],pos);
if(pos>mid)
change(mid+1,r,pr[id],pos);
tree[id][0][0]=min(tree[pl[id]][0][1]+min(tree[pr[id]][0][0],tree[pr[id]][1][0]),tree[pr[id]][1][0]+min(tree[pl[id]][0][0],tree[pl[id]][0][1]));
tree[id][0][1]=min(tree[pl[id]][0][1]+min(tree[pr[id]][0][1],tree[pr[id]][1][1]),tree[pr[id]][1][1]+min(tree[pl[id]][0][0],tree[pl[id]][0][1]));
tree[id][1][0]=min(tree[pl[id]][1][1]+min(tree[pr[id]][0][0],tree[pr[id]][1][0]),tree[pr[id]][1][0]+min(tree[pl[id]][1][0],tree[pl[id]][1][1]));
tree[id][1][1]=min(tree[pl[id]][1][1]+min(tree[pr[id]][0][1],tree[pr[id]][1][1]),tree[pr[id]][1][1]+min(tree[pl[id]][1][0],tree[pl[id]][1][1]));
// PF("<%d %d %lld(00) %lld(01) %lld(10) %lld(11)>\n",l,r,tree[id][0][0],tree[id][0][1],tree[id][1][0],tree[id][1][1]);
}
void update(int x){
int f=fa[lft[x]];
val0[f]-=min(tree[rt[lft[x]]][1][0],tree[rt[lft[x]]][1][1]);
val1[f]-=min(min(tree[rt[lft[x]]][1][0],tree[rt[lft[x]]][1][1]),min(tree[rt[lft[x]]][0][0],tree[rt[lft[x]]][0][1]));
change(dfn[lft[x]],dfn[rft[x]],rt[lft[x]],dfn[x]);
val0[f]+=min(tree[rt[lft[x]]][1][0],tree[rt[lft[x]]][1][1]);
val1[f]+=min(min(tree[rt[lft[x]]][1][0],tree[rt[lft[x]]][1][1]),min(tree[rt[lft[x]]][0][0],tree[rt[lft[x]]][0][1]));
if(f==0)
return ;
update(f);
}
char s[20];
int main(){
SF("%d%d%s",&n,&m,s);
for(int i=1;i<=n;i++)
SF("%lld",&val1[i]);
int u,v;
for(int i=1;i<n;i++){
SF("%d%d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
}
dfs(1);
prepare(1,1);
int A,B,x,y;
for(int i=1;i<=m;i++){
SF("%d%d%d%d",&A,&x,&B,&y);
ll va1=val1[A];
ll va0=val0[A];
if(x==0)
val1[A]+=INF;
else
val0[A]+=INF;
update(A);
ll vb1=val1[B];
ll vb0=val0[B];
if(y==0)
val1[B]+=INF;
else
val0[B]+=INF;
update(B);
ll res=min(min(tree[rt[1]][0][0],tree[rt[1]][0][1]),min(tree[rt[1]][1][0],tree[rt[1]][1][1]));
if(res>=INF)
res=-1;
PF("%lld\n",res);
val1[B]=vb1;
val0[B]=vb0;
update(B);
val1[A]=va1;
val0[A]=va0;
update(A);
}
}