NC54636. [CSP2019]括号树(brackets)
描述
输入描述
第一行一个整数 n,表示树的大小。
第二行一个长为 n 的由'(' 与')' 组成的括号串,第 i 个括号表示 i 号结点上的括号。
第三行包含 n− 1 个整数,第 个整数表示 i + 1 号结点的父亲编号 。
输出描述
仅一行一个整数表示答案。
示例1
输入:
5 (()() 1 1 2 2
输出:
6
说明:
树的形态如下图:C++(g++ 7.5.0) 解法, 执行用时: 69ms, 内存消耗: 12504K, 提交时间: 2022-09-30 18:38:57
#include <cstdio> typedef long long int64; const int N = 5e5 + 7; int n, pre[N], fa[N]; int64 add[N], f[N], ans; char s[N]; inline void handle(int i) { int x = fa[i]; if (s[x] == ')') x = fa[pre[x]]; if (x && s[x] == '(') f[i] = f[fa[x]] + 1, pre[i] = pre[fa[x]] ? pre[fa[x]] : x; add[i] += f[i]; } int main () { scanf("%d%s", &n, s+1); for (int i = 2, x; i <= n; ++i) { scanf("%d", &x); add[i] = add[x], fa[i] = x; if (s[i] == ')') handle(i); ans ^= 1LL * i * add[i]; } printf("%lld\n", ans); return 0; }
C++14(g++5.4) 解法, 执行用时: 132ms, 内存消耗: 12524K, 提交时间: 2019-11-21 12:30:46
#include <cstdio> int n,f[500001],pos[500001]; long long g[2][500001],ans; char s[500001]; int main(){ // freopen("brackets.in","r",stdin); // freopen("brackets.out","w",stdout); scanf("%d%s",&n,s+1); for(int x=1;x<=n;x++){ if(x>1)scanf("%d",f+x); if(s[x]=='('){ g[0][x]=0ll; pos[x]=x; g[1][x]=g[1][f[x]]; } else{ g[0][x]=pos[f[x]]?g[0][f[pos[f[x]]]]+1ll:0; pos[x]=pos[f[pos[f[x]]]]; g[1][x]=g[1][f[x]]+g[0][x]; } ans^=(1ll*x*g[1][x]); } printf("%lld\n",ans); return 0; }