zoukankan      html  css  js  c++  java
  • Codeforces208E Blood Cousins

    dsu on tree

    题目链接

    点我跳转

    题目大意

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

    解题思路

    询问一个点有多少个共同的(K)级祖先

    可以等价于问它的(K)级祖先有多少个深度为 (dep + K) 的子节点 ((dep)(K)级祖先的深度)

    那么对于每个询问要先倍增或者树链剖分求出它的(K)级祖先,再将询问保存在(K)级祖先的(vector)

    然后跑一遍 dsu on tree 统计 + 保存答案,最后再将保存的答案按照读入的询问顺序排个序输出即可

    AC_Code

    #include<bits/stdc++.h>
    #define rep(i,a,n) for (int i=a;i<=n;i++)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    using namespace std;
    const int N = 5e5 + 10;
    struct Edge{
    	int nex , to;
    }edge[N << 1];
    int head[N] , tot;
    int a[N] , dep[N] , f[N][30] , siz[N] , hson[N] , HH;
    vector<pair<int , int>>Q[N] , ans;
    unordered_map<int , int>cnt;
    void add_edge(int u , int v)
    {
    	edge[++ tot].nex = head[u];
    	edge[tot].to = v;
    	head[u] = tot;
    }
    void dfs(int u , int far)
    {
    	siz[u] = 1;
    	dep[u] = dep[far] + 1;
    	f[u][0] = far;
    	for(int i = 1 ; (1 << i) <= dep[u] ; i ++)	
    		f[u][i] = f[f[u][i - 1]][i - 1];
    	for(int i = head[u] ; i ; i = edge[i].nex)
    	{
    		int v = edge[i].to;
    		if(v == far) continue ;		
    		dfs(v , u);
    		siz[u] += siz[v];
    		if(siz[v] > siz[hson[u]]) hson[u] = v;
     	}
    } 
    void calc(int u , int far , int val , int dep)
    {
    	cnt[dep] += val;
    	for(int i = head[u] ; i ; i = edge[i].nex)
    	{
    		int v = edge[i].to;
    		if(v == far || v == HH) continue ;
    		calc(v , u , val , dep + 1);
    	}
    }
    void dsu(int u , int far, int op , int dep)
    {
    	for(int i = head[u] ; i ; i = edge[i].nex)
    	{
    		int v = edge[i].to;
    		if(v == far || v == hson[u]) continue ;
    		dsu(v , u , 0 , dep + 1);
    	}
    	if(hson[u]) dsu(hson[u] , u , 1 , dep + 1) , HH = hson[u];
    	calc(u , far , 1 , dep);
    	for(auto i : Q[u])
    	{
    		int k = i.fi , id = i.se;
    		ans.pb(make_pair(id , cnt[dep + k] - 1));
    	}
    	HH = 0;
    	if(!op) calc(u , far , -1 , dep);
    }
    int get_far(int x , int k)
    {
    	if(!k) return x;
        int t = dep[x] - k;
        per(i , 20 , 0) if(dep[f[x][i]] > t) x = f[x][i];
        return f[x][0];
    }
    signed main()
    {
    	int n , q;
    	cin >> n;
    	rep(i , 1 , n)
    	{
    		cin >> a[i];
    		if(!a[i]) continue ;
    		add_edge(i , a[i]) , add_edge(a[i] , i);
    	}
    	rep(i , 1 , n)
    	{
    		if(!a[i]) dfs(i , 0);
    	}
    	cin >> q;
    	rep(i , 1 , q)
    	{
    		int a , b;
    		cin >> a >> b;
    		int x = get_far(a , b);
    		if(!x) {ans.pb(make_pair(i , 0)) ; continue ;}
    		Q[x].pb(make_pair(b , i));
    	}
    	rep(i , 1 , n)
    	{
    		if(!a[i]) dsu(i , 0 , 0 , 1) , cnt.clear();
    	}
    	sort(ans.begin() , ans.end());
    	for(auto i : ans) cout << i.se << " ";
    	cout << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    python环境搭建以及jupyter notebook的安装和启动
    Python base(三)
    Python base(二)
    Python base(一)
    python之装饰器
    python 内置函数 (二)
    函数的简单写法
    python中set的用法
    python在终端运行时增加一些效果
    序列化写到类里
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/14028265.html
Copyright © 2011-2022 走看看