题目简介
咕咕咕。
分析
由题,显然,单个左括号无法构成贡献。
在一对括号中,右括号的贡献是 其对应的左括号 的前一个括号的贡献 \(+1\) 。
由图了解:
节点 \(x\) 的贡献和就是 \(k_x\)。
使用\(stack\)(栈) 来存储当先节点祖先的括号情况,如果栈顶元素能够与当前节点配对,则让栈顶元素出栈,否则让当前节点入栈。
为了避免子孙节点对栈的影响,也为了避免过多栈带来的程序空间不稳定,这里使用了 \(queue\)(队列)\(+BFS\)。
AC Code
#include<cstdio>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int Maxn=5e5+5;
char str[Maxn];
struct Adjacency_List{
int nxt;
int t;
}tr[Maxn];
int h[Maxn];
int tot;
void add(int x,int y){
tr[++tot].nxt=h[x];
tr[tot].t=y;
h[x]=tot;
}
struct node{
int id;
ll cnt;
stack<int>st;
};
queue<node>q;
int fa[Maxn];
ll last[Maxn];
ll k[Maxn];
int main(){
int n=read();
scanf("%s",str+1);
for(int i=2;i<=n;i++){
int x=read();
add(x,i);
fa[i]=x;
}
node fir;
fir.id=1;
fir.cnt=0;
fir.st.push(1);
q.push(fir);
while(!q.empty()){
node tmp=q.front();
q.pop();
// cout<<' '<<tmp.id;
// if(!tmp.st.empty())cout<<' '<<tmp.st.top()<<' '<<str[tmp.st.top()];
// cout<<'\n'<<" ";
for(int i=h[tmp.id];i;i=tr[i].nxt){
node t=tmp;
t.id=tr[i].t;
// cout<<t.id<<' ';
if(str[t.id]==')'&&!t.st.empty()&&str[t.st.top()]=='('){
// cout<<"\'"<<t.st.top()<<' '<<fa[t.st.top()]<<' ';
last[t.id]=last[fa[t.st.top()]]+1;
t.cnt+=last[t.id];
// cout<<t.cnt<<' '<<k[t.id]<<' ';
// cout<<last[fa[t.st.top()]]<<"\' ";
t.st.pop();
}else
t.st.push(t.id);
k[t.id]=t.cnt;
q.push(t);
}
// cout<<'\n';
}
ll cnt=0;
// for(int i=1;i<=n;i++)
// cout<<k[i]<<' ';
// cout<<'\n';
for(int i=1;i<=n;i++)
cnt^=1ll*i*k[i];
printf("%lld\n",cnt);
return 0;
}