当年我就是死在这个题目上面,错失一等奖
隔着这么久再来做思路还是很清晰的
一个树形动态规划
如果是 ( :dp[u]=dp[fa];
如果是 ):dp[u]=dp[fa]+x;
其中x是加入)后多出来的字串数,经分析可得x就是连续的括号数
连续的括号可以是( )( (()) )【算2个】
我们就要维护一个pre数组
记得要回溯,这里我直接记录栈层就可以避免退栈的过程
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=5e5+5;
int n;
char c[maxn];
ll dp[maxn],pre[maxn];
int sk[maxn];
vector<int>Q[maxn];
void calc(int u,int now){
for(int i=0;i<Q[u].size();i++){
int to=Q[u][i],tmp;
int top=now;
if(c[to]=='('){
dp[to]=dp[u];
sk[++top]=to;
if(c[u]==')')
pre[to]=pre[u];
else pre[to]=0;
}else {
if(top){
//pd=1;
tmp=sk[top];
//cout<<"tep="<<tmp<<endl;
top--;
pre[to]=pre[tmp]+1;
}
else pre[to]=0;
dp[to]=dp[u]+pre[to];
}
calc(to,top);
}
}
int main(){
//freopen("B.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=2,fa;i<=n;i++)cin>>fa,Q[fa].push_back(i);
if(c[1]=='(')
sk[1]=1;
calc(1,c[1]=='('?1:0);
ll sum=0;
for(ll i=2;i<=n;i++){
sum^=(i*dp[i]);
//if(i<=20)cout<<"dp[i]="<<dp[i]<<endl;
}//,
cout<<sum<<endl;
return 0;
}
/*
10
()(()()())
1 2 3 4 5 6 7 8 9
*/