zoukankan      html  css  js  c++  java
  • 牛客挑战赛42 小睿睿的伤害

    树上启发式合并

    枚举每个数字的所有因子,存起来

    官方题解传送门   https://ac.nowcoder.com/discuss/485120?type=101&order=0&pos=2&page=1&channel=-1&source_id=1

    题目传送门   https://ac.nowcoder.com/acm/contest/6944/B

    具体看代码吧,有注释

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<vector>
    using namespace std;
    const int maxn = 1e5 + 100;
    
    typedef long long ll;
    vector<int>G[maxn];
    void add(int be, int en) {
    	G[be].push_back(en);
    }
    int siz[maxn];
    int son[maxn];
    
    int dfs(int x, int fa) {
    	siz[x] = 1;
    	int c = 0;
    	for (int p : G[x]) {
    		if (p == fa) continue;
    		dfs(p, x);
    		siz[x] += siz[p];
    		if (siz[p] > c) {
    			c = siz[p];
    			son[x] = p;
    		}
    	}
    	return 0;
    }
    ll ans[maxn];//最大约数
    ll num[maxn];//有num对
    
    ll cnt[maxn];//公共资源,p这个数字是cnt【p】个数字的因子
    
    int list[maxn];
    vector<int>ins[maxn];
    
    
    int cal(int x, int fa, int f) {//计算cnt,f是1就是加,f=-1就是清除答案
    	for (int p : ins[list[x]]) cnt[p] += f;
    
    	for (int p : G[x]) {
    		if (p == fa) continue;
    		cal(p, x, f);
    	}
    	return 0;
    }
    
    int cal_ans(int x, int fa,int f,ll &cn,ll &an) {//重儿子算过了,只算轻儿子,cn和an就是cnt[x]和ans[x]
    
    	for (int p : ins[list[x]]) {
    		if (cnt[p]) {
    			if (p > an) {
    				an = p;
    				cn = cnt[p];
    			}
    			else if(p == an){
    				cn += cnt[p];
    			}
    		}
    	}
    
    	for (int p : G[x]) {
    		if (p == fa || p == f) continue;
    		cal_ans(p, x, f, cn, an);
    	}
    	return 0;
    }
    
    int dfs2(int x, int fa, int flag) {
    	for (int p : G[x]) {
    		if (p == fa) continue;
    		if (p == son[x]) continue;
    		dfs2(p, x, 0);
    	}
    
    	if (son[x] != 0) {
    		dfs2(son[x], x, 1);
    	}
    
    	//num[x] = ans[x] = 0;
    
    	for (int p : G[x]) {
    		if (p == fa || p == son[x]) continue;
    		cal_ans(p, x, son[x], num[x], ans[x]);
    		cal(p, x, 1);
    	}
    	
    	for (int p : ins[list[x]]) {
    		if (cnt[p]) {
    			if (p > ans[x]) {
    				ans[x] = p;
    				num[x] = cnt[p];
    			}
    			else if(p == ans[x]){
    				num[x] += cnt[p];
    			}
    		}
    		cnt[p]++;
    	}
    
    	if (flag == 0) {
    		cal(x, fa, -1);
    	}
    	return 0;
    }
    
    
    
    int main() {
    	for (int i = 1; i < maxn; i++) {
    		for (int j = 1; j*i < maxn; j++) {
    			ins[i*j].push_back(j);//i*j的所有因子由j组成
    		}
    	}
    
    	int n;
    	int x, y;
    	scanf("%d", &n);
    	for (int i = 2; i <= n; i++) {
    		scanf("%d %d", &x, &y);
    		add(x, y);
    		add(y, x);
    	}
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", &list[i]);
    	}
    
    	dfs(1, -1);//找重儿子
    
    	dfs2(1, -1, 0);//启发式合并
    
    
    	for (int i = 1; i <= n; i++) {
    		printf("%lld %lld
    ", ans[i], num[i]);
    	}
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    Ubuntu 18.04安装gcc、g++ 4.8
    Java 接口返回值集合防止空指针
    Linux CentOS7.9环境下搭建Java Web 环境
    Springboot集成UReport2
    linux 环境中 单独执行 python 脚本
    sql 注入的问题
    检验上传文件的大小
    Gunicorn使用讲解
    CentOS下安装部署对象存储服务MinIO
    阿里云CentOS7安装MySQL
  • 原文地址:https://www.cnblogs.com/lesning/p/13557091.html
Copyright © 2011-2022 走看看