control 掌控 方法记录( 二 )


control 掌控 方法记录

文章插图
为了提高效率,我们选择边建树边倍增,建树复杂度\(nlogn\) 。
void cone(int a,int b)//cone=conect{ f[a][0]=b; dep[a]=dep[b]+1; add(b,a); for(int i=1;f[f[a][i-1]][i-1];i++) {f[a][i]=f[f[a][i-1]][i-1]; }}int get_lca(int x,int y)//倍增lca{ if(dep[x]<dep[y]) swap(x,y); for(int i=19;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i]; if(x==y) return x; for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0];}再考虑回答询问 。
【control 掌控 方法记录】根据我们建树时遵循的求LCA的原则 , 发现每个询问就是求给出所有点到根的并集的节点数 。考虑将所有节点按\(dfn\)排序,则将每个节点与其相邻的节点的LCA加起来就是答案 。
control 掌控 方法记录

文章插图
void dfs(int now)//求dfn{ dfn[now]=++cnt; for(int i=head[now];i;i=E[i].nex) dfs(E[i].v);}for(int i=1,t;i<=q;i++) {re(t);for(int j=1;j<=t;j++) re(meet[j]);sort(meet+1,meet+t+1,cmp);//按dfn排序int ans=dep[meet[1]];for(int j=2;j<=t;j++) ans+=dep[meet[j]]-dep[get_lca(meet[j],meet[j-1])];printf("%d\n",ans); }完整AC代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=200005;template <typename T>inline void re(T &x) { x=0; int f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-f; for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^48); x*=f; return;}int n,q;int head[N],totr;struct edge{ int u,v,nex;}E[N<<1];void add(int u,int v){ E[totr++].u=u; E[totr].v=v; E[totr].nex=head[u]; head[u]=totr;}int f[N][20],dfn[N],meet[N],dep[N];void cone(int a,int b)//cone=conect{ f[a][0]=b; dep[a]=dep[b]+1; add(b,a); for(int i=1;f[f[a][i-1]][i-1];i++) {f[a][i]=f[f[a][i-1]][i-1]; }}int get_lca(int x,int y)//倍增lca{ if(dep[x]<dep[y]) swap(x,y); for(int i=19;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i]; if(x==y) return x; for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0];}int cnt;void dfs(int now)//求dfn{ dfn[now]=++cnt; for(int i=head[now];i;i=E[i].nex) dfs(E[i].v);}bool cmp(int a,int b){ return dfn[a]<dfn[b];}int main(){ freopen("control.in","r",stdin); freopen("control.out","w",stdout); re(n); for(int i=1,k;i<=n;i++) {re(k);int lca=0;if(k) re(lca);for(int j=1,mana;j<k;j++){re(mana);lca=get_lca(lca,mana);}cone(i,lca); } re(q); dfs(0); for(int i=1,t;i<=q;i++) {re(t);for(int j=1;j<=t;j++) re(meet[j]);sort(meet+1,meet+t+1,cmp);//按dfn排序int ans=dep[meet[1]];for(int j=2;j<=t;j++) ans+=dep[meet[j]]-dep[get_lca(meet[j],meet[j-1])];printf("%d\n",ans); } return 0;}参考

推荐阅读