bzoj 4712
Posted zhangleo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4712相关的知识,希望对你有一定的参考价值。
首先是动态dp了嘛...
然后考虑怎么做:首先列出dp方程,大概长这样:
$f[i]=min(v[i],\sum f[to])$
看着不太像动态dp呀...
考虑拿出重儿子的贡献,然后套模型,大概能构造出一个这样的东西:
设$g_i=\sum f_to[to!=son]$
$\beginpmatrix f_i\\0 \endpmatrix$ = $\beginpmatrix g_i&v_i\\ \infty& 0 \endpmatrix$ = $\beginpmatrix f_son\\0 \endpmatrix$
然后套线段树维护矩阵即可
#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],onum[200005],f[200005],ttop[200005],siz[200005],son[200005]; ll F[200005],G[200005],w[200005]; char s[2]; vector <int> v[200005]; int n,tot; void dfs(int x,int fx) siz[x]=1,f[x]=fx,dep[x]=dep[fx]+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;
以上是关于bzoj 4712的主要内容,如果未能解决你的问题,请参考以下文章