Solution
(dfs)一遍。用一个栈储存左括号,遇到一个右括号便能消掉一个左括号,可以这样来给做右括号配对。
注意形如(()())的序列有两个合法子串,((()))却只有一个。(()(()))同样有两个。所以(((())))这样的序列在搜索到最右端时对合法子串个数的贡献与(())相同。注意到若与右括号配对的左括号前面是右括号,搜索到最右端时对合法子串个数的贡献便有可能+1。
#include<bits/stdc++.h>
using namespace std;
const int N=5*1e5+10;
long long hd[N],nxt[N*2],tot,ver[N],n;
long long ans;
char c[N];
void add(int u,int v){
nxt[++tot] = hd[u];
ver[tot] = v;
hd[u] = tot;
}
long long s[N],top = 0,cont[N],sum[N],fa[N];
void dfs(int x){
int t = 0;
if(c[x] == ')' && top != 0){
t = s[top--];
cont[x] = cont[fa[t]] + 1;
}
else if(c[x] == '('){
s[++top] = x;
}
sum[x] = cont[x] + sum[fa[x]];
for(int i = hd[x]; i; i = nxt[i])
dfs(ver[i]);
if(t == 0)
if(top != 0) top--;
if(t != 0)
s[++top] = t;
}
int main(){
cin >> n;
scanf("%s",c+1);
for(int i = 2; i <= n; i++){
cin >> fa[i];
add(fa[i],i);
}
dfs(1);
for(int i = 1; i <= n; i++)
ans ^= (long long)i * sum[i];
cout << ans;
return 0;
}