zoukankan      html  css  js  c++  java
  • [CF741D]Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)

    题面

    https://codeforces.com/contest/741/problem/D

    题解

    前置知识:

    首先,对题目中”一条路径上的字符,重排后能够构成回文串“这个条件做一下转化。

    • 如果路径长是偶数,那么等价于:在这条路径上,所有字符出现的个数都是偶数。
    • 如果路径长是奇数,那么等价于:在这条路径上,有且仅有一种字符出现的个数是奇数。

    因此,我们可以对于每一个树上节点u,维护从u到根的路径上,各字符出现的个数的奇偶性。存储可以二进制压位。设这个值为(mask[u])

    那么一条路径(path(u,v))是合法的,当且仅当(pop{\_}cnt(mask[u] igoplus mask[v]) leq 1)(pop{\_}cnt[u])表示u在二进制表示下的1的个数)。它只有23种选择。

    考虑统计经过某一个点u,所有合法串的最大值ans[u]。可以使用DSU on tree来做。

    具体地说,维护f[x]表示当前所有mask[u]=x的u的深度最大值。在dfs到u点时,f中存储的将是u重儿子的信息。然后,逐一遍历u每一个轻儿子v,对于v子树中的所有点更新ans[u],再更新f。再对点u本身更新ans[u]和f。之后如果u不是fa[u]的重儿子则清空f。整个处理方法类似于点分治。

    过程中,“对于v更新ans[u]”指的是,需要找到能够与v形成合法路径的w的深度的最大值。而我们知道了mask[v],就确定了mask[w]的全部23种可能性,只需去f中查找,并取最大值得到cur。然后使ans[u]与(cur+dep[v]-2 imes dep[u])取较大值。

    总时间复杂度(O(|C|n log n))。其中(|C|)为字符集大小,本题中为22。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define rg register
    #define In inline
    
    const int N = 5e5;
    const int M = 1 << 22;
    const int inf = 0x3f3f3f3f;
    
    namespace IO{
    	In int read(){
    		int s = 0,ww = 1;
    		char ch = getchar();
    		while(ch < '0' || ch > '9'){if(ch == '-')ww = -1;ch = getchar();}
    		while('0' <= ch && ch <= '9'){s = 10 * s + ch - '0';ch = getchar();}
    		return s * ww;
    	}
    	In void write(int x){
    		if(x < 0)putchar('-'),x = -x;
    		if(x > 9)write(x / 10);
    		putchar('0' + x % 10);
    	}
    }
    using namespace IO;
    
    int f[M+5],ans[N+5];
    int mask[N+5];
    
    struct edge{
    	int next,des,ch;
    }e[N+5];
    
    int cnt;
    int head[N+5];
    
    In void addedge(int a,int b,char ch){
    	cnt++;
    	e[cnt].des = b;
    	e[cnt].next = head[a];
    	e[cnt].ch = ch - 'a';
    	head[a] = cnt; 
    }
    
    int son[N+5],sz[N+5],dfn[N+5],D[N+5],dep[N+5];
    int dn;
    
    void prepro(int u,int msk){
    	mask[u] = msk;
    	dn++;
    	D[dn] = u,dfn[u] = dn;
    	sz[u] = 1;
    	int maxn = 0;
    	for(rg int i = head[u];i;i = e[i].next){
    		int v = e[i].des;
    		dep[v] = dep[u] + 1;
    		prepro(v,msk ^ (1<<e[i].ch));
    		sz[u] += sz[v];
    		if(sz[v] > maxn)maxn = sz[v],son[u] = v;
    	}
    }		
    
    In int query(int cur){
    	int rt = f[cur];
    	for(rg int i = 0;i < 22;i++)rt = max(rt,f[cur^(1<<i)]);	
    	return rt;
    }
    
    void dfs(int u,int keep){
    	for(rg int i = head[u];i;i = e[i].next){
    		int v = e[i].des;
    		if(v == son[u])continue;
    		dfs(v,0);
    	}
    	if(son[u])dfs(son[u],1);
    	for(rg int i = head[u];i;i = e[i].next){
    		int v = e[i].des;
    		if(v == son[u])continue;
    		for(rg int j = dfn[v];j <= dfn[v] + sz[v] - 1;j++){
    			int cur = mask[D[j]];
    			ans[u] = max(ans[u],query(cur) + dep[D[j]] - 2 * dep[u]);
    		}
    		for(rg int j = dfn[v];j < dfn[v] + sz[v];j++)f[mask[D[j]]] = max(f[mask[D[j]]],dep[D[j]]);
    	}
    	ans[u] = max(ans[u],query(mask[u]) - dep[u]);
    	f[mask[u]] = max(f[mask[u]],dep[u]);
    	for(rg int i = head[u];i;i = e[i].next)ans[u] = max(ans[u],ans[e[i].des]);
    	if(!keep){
    		for(rg int i = dfn[u];i <= dfn[u] + sz[u] - 1;i++)
    			f[mask[D[i]]] = -inf;
    	}
    }
    
    int main(){
    //	freopen("CF741D.in","r",stdin);
    //	freopen("CF741D.out","w",stdout);
    	int n = read();
    	for(rg int i = 0;i < (1 << 22);i++)f[i] = -inf;
    	for(rg int i = 2;i <= n;i++){
    		int f = read();
    		char ch = getchar();
    		addedge(f,i,ch);
    	}
    	prepro(1,0);
    	dfs(1,1);
    	for(rg int i = 1;i <= n;i++){
    		write(ans[i]);
    		putchar(i == n ? '
    ' : ' ');
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    你好,这里有一份2019年目标检测指南
    谷歌2019 学术指标发榜:CVPR首次进入Top 10,何恺明论文引用最高!
    魔图互联:知识图谱推荐系统-给人们带来更个性化的推荐
    NLPer入门指南 | 完美第一步
    一文总结数据科学家常用的Python库(下)
    一文总结数据科学家常用的Python库(上)
    一文看懂NLP神经网络发展历史中最重要的8个里程碑!
    如何为计算机视觉任务选择正确的标注类型
    C. Queen Codeforces Round #549 (Div. 2) dfs
    D. Equalize Them All Codeforces Round #550 (Div. 3)
  • 原文地址:https://www.cnblogs.com/xh092113/p/12554159.html
Copyright © 2011-2022 走看看