CSP2019 T2 括号树
程序员文章站
2022-03-11 14:50:43
题目分析像我这种菜鸡,谁会直接想正解啊先看一下部分分,哇 55pts 还是条链再一看1e5,那必须DP啊dp[i][0/1]表示到第i位的总共合法括号,第i位是否匹配成功dp[i][0/1]表示到第i位的总共合法括号,第i位是否匹配成功dp[i][0/1]表示到第i位的总共合法括号,第i位是否匹配成功显然再加上一个栈即可完成转移dp[i][1]=max(dp[i−1][1],dp[i−1][0])+dp[stck[l−−]−1][0]+1dp[i][1]=max(dp[i-1][1],dp[...
分析
- 像我这种菜鸡,谁会直接想正解啊
- 先看一下部分分,哇 55pts 还是条链
- 再一看1e5,那必须DP啊
- d p [ i ] [ 0 / 1 ] 表 示 到 第 i 位 的 总 共 合 法 括 号 , 第 i 位 是 否 匹 配 成 功 dp[i][0/1]表示到第i位的总共合法括号,第i位是否匹配成功 dp[i][0/1]表示到第i位的总共合法括号,第i位是否匹配成功
- 显然再加上一个栈即可完成转移
- d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] ) + d p [ s t c k [ l − − ] − 1 ] [ 0 ] + 1 dp[i][1]=max(dp[i-1][1],dp[i-1][0])+dp[stck[l--]-1][0]+1 dp[i][1]=max(dp[i−1][1],dp[i−1][0])+dp[stck[l−−]−1][0]+1
- 但是我们发现因为我们设定的DP方程具有前缀和的性质,所以在 ()())()() 时,会出错
- 所以我们再开个数组表示在这个位置,有多少个连一起的 ()()
- 所以,我们改进一下
- d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] ) + ( a d [ i ] = a d [ s t c k [ l − − ] − 1 ] + 1 ) dp[i][1]=max(dp[i-1][1],dp[i-1][0])+(ad[i]=ad[stck[l--]-1]+1) dp[i][1]=max(dp[i−1][1],dp[i−1][0])+(ad[i]=ad[stck[l−−]−1]+1)
- 就有55pts了
- 这时想一下正解,发现,在树上只是改变了序列的顺序,和树的性质
没什么关系 - 那么直接照搬就行了(注意回溯)
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
struct node{
int next,to;
}a[N<<1];
long long dp[N][4],ad[N];
long long num[N];
int n;
int ln[N],tot;
long long ans=0;
int f[N],fa[N];
char t[N];
int l;
int stck[N];
inline void add(int x,int y) {a[++tot].next=ln[x]; ln[x]=tot; a[tot].to=y;}
inline int read()
{
int num=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') {num=(num<<1)+(num<<3)+ch-'0'; ch=getchar();}
return num*f;
}
void dfs(int x)
{
int flag=0;
if(!f[x])
{
if(l)
{
flag=stck[l--];
ad[x]=ad[fa[flag]]+1;
}
}
else if(f[x]) stck[++l]=x;
num[x]=num[fa[x]]+ad[x];
for(int i=ln[x];i;i=a[i].next)
{
int y=a[i].to;
dfs(y);
}
if(flag) stck[++l]=flag;
else if(l) l--;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) cin>>t[i];
for(int i=1;i<=n;i++) t[i]=='('?f[i]=1:f[i]=0;
for(int i=1;i<n;i++)
{
int x=read(); add(x,i+1); fa[i+1]=x;
}
dfs(1);
for(int i=1;i<=n;i++) ans^=(long long)i*num[i];
printf("%lld",ans);
/*
if(!flag)
{
int l=0;
long long now=0;
for(int i=1;i<=n;i++)
{
if(!f[i]&&l) dp[i][1]=max(dp[i-1][1],dp[i-1][0])+(ad[i]=ad[stck[l--]-1]+1);
else if(!f[i]&&!l) dp[i][0]=max(dp[i-1][1],dp[i-1][0]),l=0;
else if(f[i]) dp[i][0]=max(dp[i-1][0],dp[i-1][1]),stck[++l]=i;
ans^=(long long)i*max(dp[i][0],dp[i][1]);
}
printf("%lld\n",ans);
}
*/
return 0;
}
鸽子桌折,QvQ,嘻嘻~
一年前考的今天才补 呜呜呜菜死我了
本文地址:https://blog.csdn.net/qq_45516669/article/details/109235838