bzoj 3572 [Hnoi2014]世界树——虚树
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572
關于虛樹:https://www.cnblogs.com/zzqsblog/p/5560645.html
構造方法:
先把關鍵點按 dfs 序排序,然后依次插入樹中;
插入當前點 cr 的時候,求 lca = get_lca( cr , sta[top] ) ;如果 dep[ sta[top] ] >= dep[lca] ,就一直彈棧;
彈棧結束后,看看現在的 sta[ top ] 是不是就是 lca 了,如果不是,就 sta[ ++ top ] = lca ;同時 fa[ sta[top+1] ] = lca , fa[ lca ] = sta[ top ] ;
把 cr 也加入棧中,即 sta[++top] = cr , fa[ cr ] = lca 。
sta[ 1 ] 就是虛樹的根。
關于這道題:http://hzwer.com/6804.html
建好虛樹,先換根 dp 得出虛樹上的每個點應該被哪個點控制。換根的時候不用去掉該子樹的貢獻,因為不會有影響。
然后枚舉虛樹上的每條邊 ( cr , fa ),用倍增在邊上找到最淺的應該 “被控制 cr 的點控制” 的點 v ,然后 siz[v] - siz[cr] 和 siz[tv] - siz[v] 分別貢獻即可,其中 tv 是 fa 在 v 方向的直接孩子。
關于不是虛樹的點也不在虛樹邊上的那些點,自己的方法是在換根 dp 的時候處理;那個時候枚舉孩子 v 的時候通過找 tv ,可以知道每個虛樹上的點 cr 的不在虛樹上的孩子們的 siz 和,直接貢獻給控制 cr 的那個點即可。
#include<cstdio> #include<cstring> #include<algorithm> #define mkp make_pair #define fir first #define sec second using namespace std; int rdn() {int ret=0;bool fx=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();return fx?ret:-ret; } const int N=3e5+5,K=18; int n,hd[N],xnt,to[N<<1],nxt[N<<1]; int dfn[N],dep[N],pre[N][K+5],bin[K+5],lg[N],siz[N],sm[N]; pair<int,int> dp[N]; int m,ans[N],tt,sta[N],tot,fa[N],h2[N],xt2,t2[N<<1],nt2[N<<1]; struct Node{int v,id;}q[N];bool cmp(Node x,Node y){return dfn[x.v]<dfn[y.v];} void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;} void ad2(int x,int y){t2[++xt2]=y;nt2[xt2]=h2[x];h2[x]=xt2;} void ini_dfs(int cr,int fa) {dfn[cr]=++tot; dep[cr]=dep[fa]+1;pre[cr][0]=fa; siz[cr]=1;for(int t=1,u;(u=pre[pre[cr][t-1]][t-1]);t++)pre[cr][t]=u;for(int i=hd[cr],v;i;i=nxt[i])if((v=to[i])!=fa){ini_dfs(v,cr); siz[cr]+=siz[v];} } int get_lca(int x,int y) {if(dep[x]<dep[y])swap(x,y);for(int t=lg[dep[x]-dep[y]];t>=0;t--)if(dep[pre[x][t]]>=dep[y])x=pre[x][t];if(x==y)return x;for(int t=lg[dep[x]];t>=0;t--)if(pre[x][t]!=pre[y][t])x=pre[x][t],y=pre[y][t];return pre[x][0]; } void build() {sort(q+1,q+m+1,cmp); tt=m; tot=0;for(int i=1;i<=m;i++){int cr=q[i].v;if(!tot){sta[++tot]=cr;dp[cr]=mkp(0,cr);continue;}int lca=get_lca(cr,sta[tot]);while(dep[sta[tot]]>dep[lca])tot--;if(sta[tot]!=lca){q[++tt].v=lca; fa[sta[tot+1]]=lca;fa[lca]=sta[tot]; sta[++tot]=lca;dp[lca]=mkp(N,0);}fa[cr]=lca; sta[++tot]=cr; dp[cr]=mkp(0,cr);}for(int i=1;i<=tt;i++)if(fa[q[i].v])ad2(fa[q[i].v],q[i].v); } void dfs(int cr,int fa) {for(int i=h2[cr],v;i;i=nt2[i])if((v=t2[i])!=fa){dfs(v,cr);int tp1=dp[v].fir+dep[v]-dep[cr],tp2=dp[cr].fir;if(tp1<tp2||(tp1==tp2&&dp[v].sec<dp[cr].sec))dp[cr].fir=tp1,dp[cr].sec=dp[v].sec;} } int fnd2(int cr,int fa) {int d=dep[cr]-dep[fa]-1;while(d){int lbt=(d&-d);cr=pre[cr][lg[lbt]]; d-=lbt;}return cr; } void dfsx(int cr,int fa) {int tp1=dp[fa].fir+dep[cr]-dep[fa],tp2=dp[cr].fir;if(fa&&(tp1<tp2||(tp1==tp2&&dp[fa].sec<dp[cr].sec)))dp[cr].fir=tp1,dp[cr].sec=dp[fa].sec;int s=siz[cr];for(int i=h2[cr],v;i;i=nt2[i])if((v=t2[i])!=fa){int tv=fnd2(v,cr);s-=siz[tv]; dfsx(v,cr);}sm[dp[cr].sec]+=s-1;//-1 for zj } int fnd(int cr,int fa) {bool fg=(dp[cr].sec<dp[fa].sec);int x=dp[cr].fir,y=dp[fa].fir,d1=dep[cr],d2=dep[fa];for(int t=lg[dep[cr]-dep[fa]];t>=0;t--){int d=dep[pre[cr][t]];int u=d1-d+x,v=d-d2+y;if(u<v||(u==v&&fg))cr=pre[cr][t];}return cr; } bool In(int cr,int fa){return dfn[cr]>=dfn[fa]&&dfn[cr]<dfn[fa]+siz[fa];} void solve() {for(int i=1;i<=m;i++)sm[q[i].v]=0;int rt=sta[1]; dfs(rt,0); dfsx(rt,0);for(int i=1;i<=tt;i++)sm[dp[q[i].v].sec]++;for(int i=1;i<=tt;i++){int cr=q[i].v,f=fa[cr];if(!f) {sm[dp[cr].sec]+=n-siz[cr];continue;}int v=fnd(cr,f),tv=fnd2(cr,f);sm[dp[cr].sec]+=siz[v==f?tv:v]-siz[cr];// sm[dp[f].sec]+=siz[tv]-siz[v==f?tv:v];//tv// }for(int i=1;i<=m;i++)ans[q[i].id]=sm[q[i].v];for(int i=1;i<=m;i++)printf("%d ",ans[i]); puts(""); } int main() {n=rdn();for(int i=1,u,v;i<n;i++)u=rdn(),v=rdn(),add(u,v),add(v,u);bin[0]=1;for(int i=1;i<=K;i++)bin[i]=bin[i-1]<<1;for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;ini_dfs(1,0); int Q=rdn();while(Q--){for(int i=1;i<=tt;i++)h2[q[i].v]=0; xt2=0;for(int i=1;i<=tt;i++)fa[q[i].v]=0;/// m=rdn(); for(int i=1;i<=m;i++)q[i].v=rdn(),q[i].id=i;build(); solve();}return 0; }?
轉載于:https://www.cnblogs.com/Narh/p/10367190.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的bzoj 3572 [Hnoi2014]世界树——虚树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P4550 收集邮票-洛谷luogu
- 下一篇: 微信小程序自定义授权弹框