zoukankan      html  css  js  c++  java
  • E. Blood Cousins(dsu+倍增)

    题:https://codeforces.com/problemset/problem/208/E

    题意:给定树,问m个询问,每个询问vi,pi,要查询和vi有pi级相同祖先的对数;

    分析:支持离线且没修改,考虑dsu,,因为树每个节点向上的路径是一定的,所以我们吧询问点vi转移到pi级祖先上,然后问题就变为我们熟悉的找子树中相同高度的个数

    #include<bits/stdc++.h>
    #include<tr1/unordered_map>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int M=1e5+5;
    struct node{
        int p,id;
    };
    vector<node>q[M];
    vector<int>g[M];
    int n,grand[M][20],sz[M],deep[M],cnt[M],root,s,ans[M],son[M],vis[M];
    void dfs1(int u){
        sz[u]=1;
        for(int i=1;i<=s;i++){
            grand[u][i]=grand[grand[u][i-1]][i-1];
            if(!grand[u][i])
                break;
        }
        for(auto v:g[u]){
            if(v!=grand[u][0]){
                grand[v][0]=u;
                deep[v]=deep[u]+1;
                dfs1(v);
                sz[u]+=sz[v];
                if(sz[son[u]]<sz[v])
                    son[u]=v;
            }
        }
    }
    void init(){
        s=floor(log(1.0*n)/log(2.0));
        deep[0]=0;
        dfs1(root);
    }
    void update(int u,int fa,int k){
        cnt[deep[u]]+=k;
        for(auto v:g[u])
            if(v!=fa&&!vis[v])
                update(v,u,k);
    }
    void dfs2(int u,int fa,int sign){
        for(auto v:g[u]){
            if(v!=fa&&v!=son[u])
                dfs2(v,u,0);
        }
        if(son[u])
            dfs2(son[u],u,1),vis[son[u]]=1;
        update(u,fa,1);
        for(auto i:q[u]){
            int id=i.id;
            int p=i.p;
            ans[id]=cnt[p+deep[u]]-1;
        }
        if(son[u])
            vis[son[u]]=0;
        if(!sign)
            update(u,fa,-1);
    }
    int main(){
        scanf("%d",&n);
        for(int x,i=1;i<=n;i++){
            scanf("%d",&x);
            g[i].pb(x);
            g[x].pb(i);
        }
        init();
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int x,y,z;
            scanf("%d%d",&x,&y);
            z=y;
            for(int j=18;j>=0;j--){
                int tmp=1<<j;
                while(y-tmp>=0&&grand[x][j]!=0){
                    x=grand[x][j];
                    y-=tmp;
                }
            }
            if(y==0)
                q[x].pb(node{z,i});
        }
        dfs2(0,-1,0);
        for(int i=1;i<=m;i++)
            printf("%d ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    xml中DTD关键字说明
    xml学习笔记
    HTTP请求方法:GET和POST区别
    三种方法从键盘输入
    crontab定时器
    收藏一篇关于Asp.net Response.Filter的文章
    MethodImplOptions.Synchronized的一点讨论
    需要知道关于struct的一些事情
    Excel使用技巧总结
    HTTP协议中POST、GET、HEAD、PUT等请求方法以及一些常见错误
  • 原文地址:https://www.cnblogs.com/starve/p/12657111.html
Copyright © 2011-2022 走看看