The first is dynamic dp Well ...
Then consider how to do: dp listed first equation, probably a long way:
$f[i]=min(v[i],\sum f[to])$
He looked less like a dynamic dp ...
Consider come up with important contributions son, and then set the model, it would be able to construct such a thing:
设$g_{i}=\sum f_{to}[to!=son]$
$\begin{pmatrix} f_{i}\\0 \end{pmatrix}$ = $\begin{pmatrix} g_{i}&v_{i}\\ \infty& 0 \end{pmatrix}$ = $\begin{pmatrix} f_{son}\\0 \end{pmatrix}$
Then you can set matrix segment tree maintenance
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <vector> #define rt1 (rt<<1) #define rt2 (rt<<1)|1 #define ll long long using namespace std; const ll inf=0x3f3f3f3fll; struct MAT { ll a[2][2]; friend MAT operator * (MAT x,MAT y) { MAT ret; ret.a[0][0]=min(x.a[0][0]+y.a[0][0],x.a[0][1]+y.a[1][0]); ret.a[0][1]=min(x.a[0][1]+y.a[1][1],x.a[0][0]+y.a[0][1]); ret.a[1][0]=min(x.a[1][1]+y.a[1][0],x.a[1][0]+y.a[0][0]); ret.a[1][1]=min(x.a[1][1]+y.a[1][1],x.a[1][0]+y.a[0][1]); return ret; } }ori[200005]; MAT tree[800005]; int ed[200005],dep[200005], nnum [ 200005 ], ful [ 200005 ] f [ 200005 ], ttop [ 200005 ], siz [ 200005 ], son [ 200005 ]; II F [ 200005 ], G [ 200005 ], V [ 200005 ]; char s [ 2 ]; vector < int > y [ 200005 ]; int , n, so many; void DFS ( int x, int x) { siz [x] = 1 , F [x] = x, dep [x] = dep [x] + 1 ; for ( int i=0;i<v[x].size();i++) { int to=v[x][i]; if(to==fx)continue; dfs(to,x); siz[x]+=siz[to],son[x]=(siz[to]>siz[son[x]])?to:son[x]; } } void redfs(int x,int fx,int topx) { ttop[x]=topx,nnum[x]=++tot,onum[tot]=x; if(son[x])redfs(son[x],x,topx),ed[x]=ed[son[x]]; else ed[x]=x,F[x]=G[x]=w[x]; F[x]=F[son[x]]; for(int i=0;i<v[x].size();i++) { int to=v[x][i]; if(to==fx||to==son[x])continue; redfs(to,x,to); G[x]+=F[to]; } F[x]=min(w[x],F[x]+G[x]); } void buildtree(int rt,int l,int r) { if(l==r) { int p=onum[l]; ori[p].a[0][0]=G[p],ori[p].a[1][0]=inf,ori[p].a[1][1]=0,ori[p].a[0][1]=w[p]; if(!son[p])ori[p].a[1][0]=0; tree[rt]=ori[p]; return; } int mid=(l+r)>>1; buildtree(rt1,l,mid),buildtree(rt2,mid+1,r); tree[rt]=tree[rt1]*tree[rt2]; } void update(int rt,int l,int r,int posi) { if(l==r){tree[rt]=ori[onum[posi]];return;} int mid=(l+r)>>1; if(posi<=mid)update(rt1,l,mid,posi); else update(rt2,mid+1,r,posi); tree[rt]=tree[rt1]*tree[rt2]; } MAT query(int rt,int l,int r,int lq,int rq) { if(l>=lq&&r<=rq)return tree[rt]; int mid=(l+r)>>1; if(rq<=mid)return query(rt1,l,mid,lq,rq); else if(lq>mid)return query(rt2,mid+1,r,lq,rq); else return query(rt1,l,mid,lq,rq)*query(rt2,mid+1,r,lq,rq); } void ins(int p,ll t) { ori[p].a[0][1]+=t-w[p]; if(!son[p])ori[p].a[0][0]+=t-w[p]; w[p]=t; while(p) { MAT m0=query(1,1,n,nnum[ttop[p]],nnum[ed[p]]); update(1,1,n,nnum[p]); MAT m1=query(1,1,n,nnum[ttop[p]],nnum[ed[p]]); p=f[ttop[p]]; if(!p)break; ori[p].a[0][0]+=m1.a[0][0]-m0.a[0][0]; } } inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(); for(int i=1;i<=n;i++)w[i]=read(); for(int i=1;i<n;i++) { int x=read(),y=read(); v[x].push_back(y),v[y].push_back(x); } dfs(1,0),redfs(1,0,1); buildtree(1,1,n); int m=read(); while(m--) { scanf("%s",s); if(s[0]=='Q') { int x=read(); MAT ret=query(1,1,n,nnum[x],nnum[ed[x]]); printf("%lld\n",ret.a[0][0]); }else { int x=read(),y=read(); ins(x,w[x]+y); } } return 0; }