BZOJ 3631 松鼠的新家 树上差分
我猜会有智障说直接链剖+线段树…(希望没有) From RYC's 课件
然鹅我并不反对树剖。。。我是智障。。。QAQ
好吧还是树上差分:设 a[i]=u.a[i+1]=v
++w[u],++w[v],--w[lca(u,v)],--w[fa of lca(u,v)] 最后dfs一边统计答案
#pragma GCC optimize (2) #include<cstdio> #include<iostream> #define R register int const int M=300010; using namespace std; inline int g() { R ret=0; register char ch; while(!isdigit(ch=getchar())); do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret; } int n,cnt; int vr[M<<1],nxt[M<<1],fir[M],a[M],d[M],f[M][21],w[M],ans[M]; inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} void dfs(int u) { for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(d[v]) continue; d[v]=d[u]+1; R p=u; f[v][0]=u; for(R j=0;f[p][j];++j) f[v][j+1]=f[p][j],p=f[p][j]; dfs(v); } } inline void lca(int u,int v) { if(d[u]<d[v]) swap(u,v); R uu=u,vv=v; for(R j=20;j>=0;--j) if(d[f[u][j]]>=d[v]) u=f[u][j]; if(u==v) {--w[u],--w[f[u][0]],++w[uu],++w[vv]; return ;} for(R j=20;j>=0;--j) if(f[u][j]!=f[v][j]) u=f[u][j],v=f[v][j]; u=f[u][0]; ++w[uu],++w[vv],--w[u],--w[f[u][0]]; return ; } void dfs2(int u) { for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(v==f[u][0]) continue; dfs2(v); w[u]+=w[v]; } } signed main() { n=g(); for(R i=1;i<=n;++i) a[i]=g(); for(R i=1,u,v;i<n;++i) u=g(),v=g(),add(u,v),add(v,u); d[1]=1; dfs(1); for(R i=1;i<n;++i) lca(a[i],a[i+1]); dfs2(1); for(R i=1;i<=n;++i) printf("%d\n",(i==a[1]?w[i]:w[i]-1)); }
2019.04.22