zoukankan      html  css  js  c++  java
  • Codeforces 741D 【Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths】

    Description

    传送门


    Solution

    将字符串的路径看做二进制数,那么一个路径上的字符能重新调整成回文串的充要条件是从根到两个点的二进制数异或和为(0)或者(2)的幂。这是因为在一个回文串里,出现次数为奇数的字符只能有一个或者没有。

    那么问题现在变成(x)的子树里找最大的(dep_a + dep_b - dep_{lca(a, b)})。我们可以考虑钦定两个点的(lca)(x),最后用(x)的子树的值更新它即可。

    这样我们就有了(dsu on tree)的思路。那么如何保证两个点的(lca)就是(x)点呢?只需要一条链一条链的进行处理,这样任意两点的(lca)必然就是(x)。将二进制数为(s)的最深深度记录下来,枚举一下二进制数互相异或得到的值就行了。


    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 500000;
    
    int head[N + 50], num, a[N + 50], n, siz[N + 50], dep[N + 50], ans[N + 50], maxson[N + 50], s[N + 50], maxv, f[N * 20], inf;
    
    struct Node
    {
    	int next, to;
    } edge[N + 50];
    
    void Addedge(int u, int v)
    {
    	edge[++num] = (Node){head[u], v};
    	head[u] = num;
    	return;
    }
    
    void Dfs1(int x, int fa)
    {
    	siz[x] = 1; dep[x] = dep[fa] + 1;
    	if (x != 1) s[x] = s[fa] ^ (1 << a[x]);
    	for (int i = head[x]; i; i = edge[i].next)
    	{
    		int v = edge[i].to;
    		Dfs1(v, x);
    		siz[x] += siz[v];
    		if (siz[v] > siz[maxson[x]]) maxson[x] = v;
    	}
    	return;
    }
    
    void Calc(int rt, int x)
    {
    	int now = s[x];
    	maxv = max(maxv, f[now] + dep[x] - 2 * dep[rt]);
    	if ((s[x] ^ s[rt]) == 0) maxv = max(maxv, dep[x] - dep[rt]);
    	for (int i = 0; i < 22; i++)
    	{
    		now = (1 << i) ^ s[x];
    		maxv = max(maxv, f[now] + dep[x] - 2 * dep[rt]);
    		if ((s[x] ^ s[rt]) == (1 << i)) maxv = max(maxv, dep[x] - dep[rt]);
    	}
    	for (int i = head[x]; i; i = edge[i].next)
    	{
    		int v = edge[i].to;
    		Calc(rt, v);
    	} 
    	return;
    }
    
    void Change(int x, int k)
    {
    	if (k) f[s[x]] = max(f[s[x]], dep[x]);
    	else f[s[x]] = inf;
    	for (int i = head[x]; i; i = edge[i].next) Change(edge[i].to, k);
    	return;
    }
    
    void Dfs2(int x, int remain)
    {
    	for (int i = head[x]; i; i = edge[i].next)
    	{
    		int v = edge[i].to;
    		if (v == maxson[x]) continue;
    		Dfs2(v, 0); 
    	}
    	if (maxson[x]) Dfs2(maxson[x], 1);
    	maxv = 0; int now = s[x];
    	maxv = max(maxv, f[now] - dep[x]);
    	for (int i = 0; i < 22; i++)
    	{
    		now = (1 << i) ^ s[x];
    		maxv = max(maxv, f[now] - dep[x]);
    	}
    	for (int i = head[x]; i; i = edge[i].next)
    	{
    		int v = edge[i].to;
    		if (v == maxson[x]) continue;
    		Calc(x, v); Change(v, 1);
    	}
    	ans[x] = maxv;
    	if (!remain) 
    	{
    		for(int i = head[x]; i; i = edge[i].next)
    			Change(edge[i].to, 0);
    		f[s[x]] = inf; 
    	}
    	else f[s[x]] = max(f[s[x]], dep[x]);
    	return;
    }
    
    void Erase(int x)
    {
    	for (int i = head[x]; i; i = edge[i].next)
    	{
    		int v = edge[i].to; Erase(v);
    		ans[x] = max(ans[x], ans[v]);
    	}
    	return;
    }
    
    int main()
    {
    	scanf("%d", &n);
    	char tmp;
    	for (int i = 2, fa; i <= n; i++)
    	{
    		scanf("%d", &fa);
    		cin >> tmp;
    		Addedge(fa, i); a[i] = tmp - 'a';
    	}
    	Dfs1(1, 0); 
    	memset(f, 128, sizeof(f)); inf = f[0];
    	Dfs2(1, 0);
    	Erase(1);
    	for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    并发容器和框架之ConcurrentHashMap
    Java的LockSupport工具,Condition接口和ConditionObject
    从源码来看ReentrantLock和ReentrantReadWriteLock
    VMWARE虚拟机上Terminal中使用sudo出现”** 不在sudoers文件中,此事将被警告 “错误
    mac下idea运行项目慢问题解决
    Idea 只修改编辑区主题
    redis内部数据结构的数据结构
    mysql存储过程详解
    HashMap中resize()剖析
    谈Redis的refash的增量式扩容
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13097708.html
Copyright © 2011-2022 走看看