Codeforces 741 D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

思路:

树上启发式合并

从根节点出发到每个位置的每个字符的奇偶性记为每个位置的状态,每次统计一下每个状态的最大深度

为了保证链经过当前节点u,我们先计算每个子树的答案,再更新子树状态对深度的贡献。

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

inline int read() {
    int a = 1, b = 0;
    char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘) {
        if(ch == ‘-‘) a = -1;
        ch = getchar();
    }
    while(‘0‘ <= ch && ch <= ‘9‘) {
        b = b*10 + ch-‘0‘;
        ch = getchar();
    }
    return a*b;
}
const int N = 5e5 + 5, M = 5e6 + 5;
const int INF = 1e8;
vector<pii> g[N];
int n, p, dp[N], sz[N], son[N], deep[N], st[N], mx[M];
char c[2];
void get_son(int u, int o) {
    sz[u] = 1;
    deep[u] = deep[o] + 1;
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        int w = g[u][i].se;
        st[v] = st[u] ^ (1<<w);
        get_son(v, u);
        if(sz[v] > sz[son[u]]) son[u] = v;
        sz[u] += sz[v];
    }
}
void CAL(int p, int u) {
    if(mx[st[u]] >= 0) dp[p] = max(dp[p], mx[st[u]]+deep[u]-2*deep[p]);
    for (int i = 0; i < 22; ++i) {
        if(mx[st[u]^(1<<i)] >= 0) dp[p] = max(dp[p], mx[st[u]^(1<<i)]+ deep[u]-2*deep[p]);
    }
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        CAL(p, v);
    }
}
void ADD(int u) {
    mx[st[u]] = max(mx[st[u]], deep[u]);
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        ADD(v);
    }
}
void DELETE(int u) {
    if(mx[st[u]] >= 0) mx[st[u]] = -INF;
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        DELETE(v);
    }
}
void dfs(int u) {
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        if(v != son[u]) {
            dfs(v);
            DELETE(v);
        }
    }

    if(son[u]) dfs(son[u]);

    if(mx[st[u]] >= 0) dp[u] = mx[st[u]] - deep[u];
    for (int i = 0; i < 22; ++i) {
        if(mx[st[u]^(1<<i)] >= 0) dp[u] = max(dp[u], mx[st[u]^(1<<i)] - deep[u]);
    }

    mx[st[u]] = max(mx[st[u]], deep[u]);
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        if(v != son[u]) {
            CAL(u, v);
            ADD(v);
        }
    }
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i].fi;
        dp[u] = max(dp[u], dp[v]);
    }
}
int main() {
    n = read();
    for (int i = 2; i <= n; ++i) {
        p = read();
        scanf("%s", c);
        g[p].pb({i, c[0]-‘a‘});
    }
    get_son(1, 0);
    for (int i = 0; i < M; ++i) mx[i] = -INF;
    dfs(1);
    for (int i = 1; i <= n; ++i) printf("%d%c", dp[i], " \n"[i==n]);
    return 0;
}

原文地址:https://www.cnblogs.com/widsom/p/10773406.html

时间: 2024-11-03 21:29:03

Codeforces 741 D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths的相关文章

Codeforces Round #245 (Div. 1)——Guess the Tree

本文出自:http://blog.csdn.net/svitter 实验环境:Myeclipse10 + tomcat7.0 有时间会写windows和linux下的tomcat配置,现在时间有限,暂且不写了..有些东西也是没有理解透彻. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <%@ page language="java" contentType="

cfodeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

题目链接:Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 第一次写\(dsu\ on\ tree\),来记录一下 \(dsu\ on\ tree\)主要维护子树信息,往往可以省掉一个数据结构的启发式合并.大体思路如下: 轻重链路径剖分之后,对每个点先递归处理他的所有轻儿子,每次处理完轻儿子之后把这棵子树的信息清空.最后再来处理重孩子,重儿子的信息就可以不用清空了.由于我们是用一个全局数组来记录信息的,重儿子子树的信息就仍然保留

Codeforces 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

Description 以\(1\) 为根 的 \(n\) 个节点的树,每条边有一个颜色 \(x\),求每一个点的子树内的好的路径的最长长度 一条路径被定义为好的当且仅当把所有经过的边的字母经过排列之后可以变成回文 题面 Solution 理解了一下 \(dsu\,on\,tree\),相比普通的启发式,省去了高级的数据结构,并省下了大量空间 好的路径实际上就是出现奇数次的字母不多于一个,字符集只有 \(22\),可以状压起来 对于一条路径的异或和实际上可以看成 \(dis[x]\)^\(dis

Codeforces.741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree 思路)

题目链接 \(Description\) 给定一棵树,每条边上有一个字符(a~v).对每个节点,求它的子树中一条最长的路径,满足 路径上所有边上的字符可以重新排列成一个回文串.输出其最长长度. \(n\leq 5\times10^5\). \(Solution\) 可以构成回文串,即要么所有字符都出现了偶数次,要么有一个出现了奇数次.其余都出现了偶数次. 转化为异或!把每个字符c(0~21)映射到1<<c上去. 令\(s[x]\)表示根节点到\(x\)路径上边权的异或和.那么路径\((u,v)

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/problem/C Description Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numb

Codeforces Round #124 (Div. 1) C. Paint Tree(极角排序)

C. Paint Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a tree with n vertexes and n points on a plane, no three points lie on one straight line. Your task is to paint

343D/Codeforces Round #200 (Div. 1) D. Water Tree dfs序+数据结构

D. Water Tree Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a reservoir which can be either empty or filled with water. The vertices of the tree are numbered from 1 to n with the root at vertex 1. For

Codeforces 850C E. Arpa and a game with Mojtaba

对每个数统计其素数因子各次方数的数,然后通过y = (x>>i) | (x&((1<<(i-1))-1)) 模拟delete x and add  to the list 操作,用grund函数将每个因子的情况映射为NIM问题中一个堆的情况,再按NIM问题的求解方法求解 参考链接 https://www.topcoder.com/community/data-science/data-science-tutorials/algorithm-games/ #include&l

Codeforces Round #168 (Div. 1) B. Zero Tree 树形dp

题目链接: http://codeforces.com/problemset/problem/274/B 题意: 给出一棵树,每个点有权值,每次操作可以对一个联通子集中的点全部加1,或者全部减1,且每次操作必须包含点1,问最少通过多少次操作可以让整棵树每个点的权值变为0. 思路: http://blog.csdn.net/qq_24451605/article/details/48622953 定义状态up[u],down[u]代表点u被加操作的次数和点u被减操作的次数 因为必须包含点1,所以我