• #长链剖分#CF208E Blood Cousins


    题目

    给你一片森林,每次询问一个点与多少个点拥有共同的 (K) 级祖先


    分析

    (dp[x][d])表示以(x)为根节点时深度为(d)的个数,
    那么(dp[x][d]=sum{dp[y][d-1]})
    这个考虑用长链剖分维护就可以做到(O(n))


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register 
    using namespace std;
    const int N=100011; struct node{int y,next;}e[N],E[N]; int puf[N]; int *dp[N],*st=puf;
    int dep[N],dfn[N],sta[N],big[N],F[N],Top,d[N],ans[N],n,Q,et,rt[N],as[N],hs[N],Hs[N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline void add(int x,int y){
    	if (!x) {rt[++rt[0]]=y; return;}
        e[++et]=(node){y,as[x]},as[x]=et;
    }
    inline void dfs1(int x,int fa){
    	dep[x]=dep[fa]+1,sta[++Top]=x;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fa){
    		dfs1(e[i].y,x);
    		if (d[e[i].y]>d[big[x]]) big[x]=e[i].y;
    	}
    	for (rr int i=hs[x];i;i=E[i].next)
    	    if (Top>=E[i].y) F[i]=sta[Top-E[i].y];
    	--Top,d[x]=d[big[x]]+1;
    }
    inline void dfs2(int x,int fa){
    	dp[x][0]=1;
    	if (!big[x]) return;
    	dp[big[x]]=dp[x]+1,dfs2(big[x],x);
    	for (rr int i=as[x];i;i=e[i].next)
     	if (e[i].y!=fa&&e[i].y!=big[x]){
    		dp[e[i].y]=st,st+=d[e[i].y],dfs2(e[i].y,x);
    		for (rr int j=1;j<=d[e[i].y];++j)
    		    dp[x][j]+=dp[e[i].y][j-1];
    	}
    	for (rr int i=hs[x];i;i=E[i].next)
    	    ans[i]=dp[x][E[i].y]-1;
    }
    signed main(){
    	n=iut();
    	for (rr int i=1;i<=n;++i) add(iut(),i);
    	Q=iut();
    	for (rr int i=1;i<=Q;++i){
    		rr int x=iut(),d=iut();
    		E[i]=(node){d,hs[x]},hs[x]=i;
    	}
    	for (rr int i=1;i<=rt[0];++i) dfs1(rt[i],0);
    	for (rr int i=1;i<=n;++i) Hs[i]=hs[i],hs[i]=0;
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=Hs[i],t;j;j=t){
    		t=E[j].next;
    		if (F[j]) E[j]=(node){E[j].y,hs[F[j]]},hs[F[j]]=j;
    	}
    	for (rr int i=1;i<=rt[0];++i)
    		dp[rt[i]]=st,st+=d[rt[i]],dfs2(rt[i],0);
    	for (rr int i=1;i<=Q;++i) print(ans[i]),putchar(32);
        return 0;
    }
    
  • 相关阅读:
    吾爱破解2018-2020优秀文章合集
    分享一个零基础入门学习Python(第2版)带课件及源码
    fiddler抓包工具详细配置方法,多图详细(转)
    浏览器提速,支持95%的国产浏览器(转)
    易语言5.92学习版
    Android Studio 之 ViewModel (转)
    一款易语言软件启动前修改(劫持DLL注入修改)【转】
    某桌球辅助登录算法分析并转本地验证
    软件虚拟机保护分析资料整理
    HttpCanary其他教程
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14980733.html
Copyright © 2020-2023  润新知