zoukankan      html  css  js  c++  java
  • loj6674. 赛道修建

    题意

    略。

    题解

    完全为了水博客
    处理出每个点bitset的后缀或(从所有儿子结点继承来)和每个点的bitset的前缀或(从父亲的方向继承来)。
    bitset以路径长度为关键字。这样以一个点为起点的路径长度种数就是这个点上前后缀bitset或的count()
    这样可以做到(mathcal O(frac {n ^ 2}{omega}))
    但是要注意的是,一个点的前缀或必须和其兄弟节点一起在其父亲节点处处理(还是处理一个前缀和数组),否则复杂度就不对了。

    #pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 5e4 + 5;
    int n, a[N];
    vector <int> g[N];
    bitset <N> tmp, pre[N], suf[N], s[N];
    void dfs (int x, int p) {
    	suf[x][0] = a[x];
    	for (auto y : g[x]) {
    		if (y != p) {
    			dfs(y, x);
    			suf[x] |= suf[y] << 1;
    		}
    	}
    }
    void sfd (int x, int p) {
    	vector <int> ch(0);
    	tmp = pre[x], tmp[0] = a[x];
    	for (auto y : g[x]) {
    		if (y != p) {
    			ch.push_back(y);
    		}
    	}
    	s[ch.size()].reset();
    	for (int i = (int)ch.size() - 1; i >= 0; --i) {
    		s[i] = s[i + 1] | (suf[ch[i]] << 1);
    	}
    	for (int i = 0; i < (int)ch.size(); ++i) {
    		pre[ch[i]] = (tmp | s[i + 1]) << 1;
    		tmp |= suf[ch[i]] << 1;
    	}
    	for (auto y : ch) {
    		sfd(y, x);
    	}
    }
    int main () {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", &a[i]);
    	}
    	for (int i = 1, x, y; i < n; ++i) {
    		scanf("%d%d", &x, &y);
    		g[x].push_back(y), g[y].push_back(x);
    	}
    	dfs(1, 0), sfd(1, 0);
    	for (int i = 1; i <= n; ++i) {
    		printf("%d
    ", (int)(pre[i] | suf[i]).count());
    	}
    	return 0;
    }
    
  • 相关阅读:
    Flutter
    Flutter
    Flutter
    使用Sublime Text 3作为React Native的开发IDE
    新建React Native项目步骤
    【一些容易忘记的node的npm命令】【收集】
    前端异步的一种方法库:axios
    【react】兄弟组件的通信方式,传统非redux
    【js】关于闭包和匿名函数
    【js】手机浏览器端唤起app,没有app就去下载app 的方法
  • 原文地址:https://www.cnblogs.com/psimonw/p/11637399.html
Copyright © 2011-2022 走看看