本题,题目长,但是实际想起来十分简单。
首先,对于树上的每一个后括号,我们很容易知道,他的贡献值等于上一个后括号的贡献值 + 1。(当然,前提是要有人跟他匹配,毕竟题目中要求了,是不同的子串。)
那么,如何记录是否有人跟他匹配?? 也很好想。。。 用一个栈来维护(同时也方便我们记录上一个后括号所在的位置。)
那么,求总贡献值呢?? 更好办了。 直接等于他爸爸 + 他自己的呗!!
结束了~~~
#include <bits/stdc++.h> using namespace std; #define N 600010 #define ll long long inline ll read(){ ll x = 0, s = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-')s = -1; c = getchar(); } while(isdigit(c)){ x = (x << 1) + (x << 3) + (c ^ '0'); c = getchar(); } return x * s; } int fa[N]; ll sum[N], lst[N]; struct node{ int v, next; } t[N]; int f[N]; int a[N]; char c[N]; int bian = 0; inline void add(int u, int v){ t[++bian] = (node){v, f[u]}; f[u] = bian; return ; } int stac[N], top = 0; void dfs(int now){ int temp = 0;; if(c[now] == '('){ stac[++top] = now; } else if(c[now] == ')'){ if(top){ temp = stac[top]; lst[now] = lst[fa[temp]] + 1; top--; } } sum[now] = sum[fa[now]] + lst[now]; for(int i = f[now]; i; i = t[i].next){ int v = t[i].v; dfs(v); } if(temp != 0) stac[++top] = temp; else if(top) top--; return ; } int main(){ int n = read(); scanf("%s", c + 1); for(int i = 2;i <= n; i++){ int x = read(); add(x, i); fa[i] = x; } dfs(1); ll ans = 0; for(ll i = 1;i <= n; i++) ans ^= i * sum[i]; printf("%lld ", ans); return 0; }