P5658 [CSP-S2019] 括号树

P5658 CSP-S2019括号树

先考虑线性的情况
.....(....)
如果是(则将其左边的答案加入栈,这个点的答案为0
如果是)则将栈顶左边的答案+1作为贡献(答案)
每个点的答案为以这个点为右端点的字串的个数
统计答案时前缀和即可
书上的同理,将“左边”改为“父节点”
注意回溯和栈是空的的情况

点击查看代码
#include <vector>
#include <stdio.h>
#include <string.h>
const int N = 5e5 + 5;
typedef long long LL;
std::vector<int> sons[N];
int n, fa[N], stk[N], top;
char str[N];
int res[N];
LL now, ans;
void dfs(int u) {
    int tmp = -1;
    if(str[u] == '(') stk[++ top] = res[fa[u]];
    else if(top) res[u] = (tmp = stk[top]) + 1, top --;
    for(int v : sons[u]) dfs(v);
    if(str[u] == '(') top --;
    else if(tmp != -1) stk[++ top] = tmp;
}
void calc(int u) {
    now += res[u], ans ^= u * now;
    for(int v : sons[u]) calc(v);
    now -= res[u];
}
int main() {
    scanf("%d%s", &n, str + 1);
    for(int i = 2; i <= n; i ++)
        scanf("%d", fa + i), sons[fa[i]].push_back(i);
    dfs(1), calc(1), printf("%lld\n", ans);
    return 0;
}

posted @ 2022-09-29 13:53  azzc  阅读(43)  评论(0)    收藏  举报