• 树上启发式合并学习笔记


    参考链接:https://www.cnblogs.com/zzqsblog/p/6146916.html

    树上启发式合并可以在O(nlogn)的时间内解决很多关于树的无修改询问,比如每颗子树中出现的最多的颜色等。

    树上启发式算法流程:

    1 先dfs一次,记录每个节点的重儿子。(和树剖的预处理差不多)。

    2 第二次dfs,这次dfs用来解决关于子树的询问的问题,分为3步:

      1 先dfs非重儿子节点,即解决非重儿子子树的询问问题,求解后把信息清零。

      2 dfs重儿子节点,即解决重儿子子树的询问问题,求解后不用把信息清零。

      3 用另一个dfs函数统计非重儿子的子树的信息(只是统计信息),之后便得到了这个节点的询问的答案。

      4 根据传进来的参数决定信息是否清零。

    代码:

    CF 600E:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =100010;
    int head[maxn], Next[maxn*2], ver[maxn*2];
    int cnt[maxn], col[maxn], sz[maxn], son[maxn], tot;
    bool skip[maxn];
    long long ans[maxn], sum;
    int mx;
    void add(int x, int y) {
    	ver[++tot] = y;
    	Next[tot] = head[x];
    	head[x] = tot;
    }
    void get_son(int x,int f = 0) {
    	sz[x] = 1;
    	for(int i =head[x]; i; i = Next[i]) {
    		int y = ver[i];
    		if(y == f) continue;
    		get_son(y,x);
    		sz[x] += sz[y];
    		if(sz[y] > sz[son[x]])
    			son[x] = y;
    	}
    }
    
    void update(int x, int f, int k) {
    	cnt[col[x]] += k;
    	if(k > 0 && cnt[col[x]] >= mx) {
    		if(cnt[col[x]] > mx)
    			sum = 0, mx = cnt[col[x]];
    		sum += col[x];
    	}
    	for(int i = head[x]; i; i = Next[i]) {
    		int y  = ver[i];
    		if(y != f && !skip[y])
    			update(y,x,k);
    	}
    }
    
    void dfs(int x, int f = 0, int kep = 0) {
    	for(int i = head[x]; i ; i = Next[i]) {
    		int y = ver[i];
    		if(y != f && y != son[x]) {
    			dfs(y, x);
    		}
    	}
    	if(son[x]) {
    		dfs(son[x], x, 1), skip[son[x]] = 1;
    	}
    	update(x,f,1);
    	ans[x] = sum;
    	if(son[x]) skip[son[x]] = 0;
    	if(!kep) {
    		update(x, f, -1);
    		mx = sum = 0;
    	}
    }
    
    int main() {
    	int n;
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++) scanf("%d", col + i);
    	for(int i = 1; i < n; i++) {
    		int x, y;
    		scanf("%d%d", &x, &y);
    		add(x, y);
    		add(y, x);
    	}
    	get_son(1);
    	dfs(1);
    	for(int i = 1; i <= n; i++)
    		printf("%lld ", ans[i]);
    }
    

    CF 741D:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =500010;
    int head[maxn], Next[maxn*2], ver[maxn*2], edge[maxn*2];
    int cnt[maxn], sz[maxn], son[maxn], tot;
    const int S = 'v' - 'a' + 1, INF = 1e9;
    int lca_deep, skip, now;
    int dp[maxn], re[1<<S], a[maxn], deep[maxn];
    void add(int x, int y, int z) {
    	ver[++tot] = y;
    	edge[tot] = z;
    	Next[tot] = head[x];
    	head[x] = tot;
    }
    
    void get_son(int x,int f = 0) {
    	sz[x] = 1;
    	for (int i =head[x]; i; i = Next[i]) {
    		int y = ver[i];
    		if(y == f) continue;
    		a[y] = a[x] ^ edge[i];
    		deep[y] = deep[x] + 1;
    		get_son(y,x);
    		sz[x] += sz[y];
    		if(sz[y] > sz[son[x]])
    			son[x] = y;
    	}
    }
    void clr(int x) {
    	re[a[x]] = -INF;
    }
    void change(int x) {
    	now = max(now, re[a[x]] + deep[x]  -lca_deep * 2);
    	for (int i = 0; i < S; i++) {
    		now = max(now, re[a[x] ^ (1 << i)] + deep[x] - lca_deep * 2);
    	}
    }
    void maintain(int x) {
    	re[a[x]] = max(re[a[x]], deep[x]);
    }
    template <void(*func)(int)> 
    void update(int x, int f) {
    	func(x);
    	for (int i = head[x]; i; i = Next[i]) {
    		int y  = ver[i];
    		if(y != f && y != skip)
    			update<func>(y,x);
    	}
    }
    void dfs(int x, int f = 0, int kep = 0) {
    	for (int i = head[x]; i ; i = Next[i]) {
    		int y = ver[i];
    		if(y != f && y != son[x]) {
    			dfs(y, x);
    		}
    	}
    	if (son[x]) {
    		dfs(son[x], x, 1), skip = son[x];
    	}
    	lca_deep = deep[x];
    	for (int i  = head[x]; i; i = Next[i]) {
    		int y = ver[i];
    		if (y != f) 
    			dp[x] = max(dp[x], dp[y]);
    	}
    	for (int i = head[x]; i ; i = Next[i]) {
    		int y = ver[i];
    		if(y != f && y != son[x]) {
    			update<change>(y,x);
    			update<maintain>(y,x);
    		}
    	}
    	change(x), maintain(x);
    	dp[x] = max(dp[x], now);
    	skip = 0;
    	if (!kep) {
    		update<clr>(x, f);
    		now = -INF;
    	}
    }
    
    int main() {
    	int n;
    	scanf("%d", &n);
    	for(int i = 0; i < (1<<S); i++) {
    		re[i] = - INF;
    	} 
    	for(int i = 2; i <= n; i++) {
    		int x;
    		char z[3];
    		scanf("%d%s", &x, z);
    		add(i, x, 1 << (z[0] - 'a'));
    		add(x, i, 1 << (z[0] - 'a'));
    	}
    	get_son(1);
    	dfs(1);
    	for(int i = 1; i <= n; i++)
    		printf("%d ", dp[i]);
    }
    

    CF 1009F:

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int maxn =1000010;
    int head[maxn], Next[maxn*2], ver[maxn*2];
    int cnt[maxn], col[maxn], sz[maxn], son[maxn], deep[maxn], tot;
    int skip;
    int ans[maxn], mx, tmp;
    void add(int x, int y) {
    	ver[++tot] = y;
    	Next[tot] = head[x];
    	head[x] = tot;
    }
    void get_son(int x,int f = 0) {
    	sz[x] = 1;
    	for(int i =head[x]; i; i = Next[i]) {
    		int y = ver[i];
    		if(y == f) continue;
    		deep[y]  = deep[x] + 1;
    		get_son(y,x);
    		sz[x] += sz[y];
    		if(sz[y] > sz[son[x]])
    			son[x] = y;
    	}
    }
    
    void update(int x, int f, int k) {
    	cnt[deep[x]] += k;
    	if (k > 0 && cnt[deep[x]] >= mx) {
    		if (cnt[deep[x]] > mx) {
    			mx = cnt[deep[x]];
    			tmp = deep[x];
    		} else if (tmp > deep[x]) {
    			tmp = deep[x];
    		}
    	}
    	for(int i = head[x]; i; i = Next[i]) {
    		int y  = ver[i];
    		if(y != f && y != skip)
    			update(y,x,k);
    	}
    }
    
    void dfs(int x, int f = 0, int kep = 0) {
    	for(int i = head[x]; i ; i = Next[i]) {
    		int y = ver[i];
    		if(y != f && y != son[x]) {
    			dfs(y, x);
    		}
    	}
    	if(son[x]) {
    		dfs(son[x], x, 1), skip = son[x]; 
    	}
    	update(x,f,1);
    	ans[x] = tmp - deep[x];
    	skip = 0;
    	if(!kep) {
    		update(x, f, -1);
    		mx = 0;
    		tmp = INF;
    	}
    }
    
    int main() {
    	int n;
    	scanf("%d", &n);
    	for(int i = 1; i < n; i++) {
    		int x, y;
    		scanf("%d%d", &x, &y);
    		add(x, y);
    		add(y, x);
    	}
    	get_son(1);
    	dfs(1);
    	for(int i = 1; i <= n; i++)
    		printf("%d ", ans[i]);
    }
    

    CF 570D

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =500010;
    int head[maxn], Next[maxn*2], ver[maxn*2];
    int cnt[maxn], sz[maxn], son[maxn], deep[maxn], tot, skip;
    int ans[maxn], a[maxn];
    vector<int> q[maxn], id[maxn];
    bitset<26> re[maxn];
    int mx;
    void add(int x, int y) {
    	ver[++tot] = y;
    	Next[tot] = head[x];
    	head[x] = tot;
    }
    void get_son(int x,int f = 0) {
    	sz[x] = 1;
    	for(int i =head[x]; i; i = Next[i]) {
    		int y = ver[i];
    		if(y == f) continue;
    		deep[y] = deep[x] + 1; 
    		get_son(y,x);
    		sz[x] += sz[y];
    		if(sz[y] > sz[son[x]])
    			son[x] = y;
    	}
    }
    
    void update(int x, int f) {
    	re[deep[x]][a[x]] =  re[deep[x]][a[x]] ^ 1;
    	for(int i = head[x]; i; i = Next[i]) {
    		int y  = ver[i];
    		if(y != f && y!= skip)
    			update(y, x);
    	}
    }
    
    void dfs(int x, int f = 0, int kep = 0) {
    	for(int i = head[x]; i ; i = Next[i]) {
    		int y = ver[i];
    		if(y != f && y != son[x]) {
    			dfs(y, x);
    		}
    	}
    	if(son[x]) {
    		dfs(son[x], x, 1), skip = son[x];
    	}
    	update(x,f);
    	for(int i = 0; i < q[x].size(); i++) {
    		if(re[q[x][i]].count() <= 1 ) ans[id[x][i]] = 1;
    		else ans[id[x][i]] = 0;
    	}
    	skip = 0;
    	if(!kep) {
    		update(x, f);
    	}
    }
    
    int main() {
    	int n, m;
    	int x, y;
    	char s[maxn];
    	scanf("%d%d", &n, &m);
    	for (int i = 2; i <= n; i++) {
    		scanf("%d", &x);
    		add(x, i);
    		add(i, x);
    	}
    	scanf("%s", s + 1);
    	for (int i = 1; i <= n; i++) {
    		a[i] = s[i] - 'a';
    	}
    	for(int i = 1; i <= m; i++) {
    		scanf("%d%d",&x, &y);
    		q[x].push_back(y);
    		id[x].push_back(i);
    	}
    	deep[1] = 1;
    	get_son(1);
    	dfs(1);
    	for(int i = 1; i <= m; i++) {
    		if(ans[i] == 1)printf("Yes
    ");
    		else printf("No
    ");
    	}
    }
    
  • 相关阅读:
    HDU 1495 广度优先搜索
    oj 1792:迷宫 广搜和深搜
    oj 1756:八皇后 搜索
    OJ1700 八皇后问题 基本搜索算法
    PAT A1020
    PAT A1103
    PAT A1046 Shortest Distance
    PAT A1059
    PAT B1013
    二分查找
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10269687.html
Copyright © 2020-2023  润新知