欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

CSP2019 T2 括号树

程序员文章站 2022-06-22 09:33:22
题目分析像我这种菜鸡,谁会直接想正解啊先看一下部分分,哇 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]ii
  • 显然再加上一个栈即可完成转移
  • 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[i1][1],dp[i1][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[i1][1],dp[i1][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

相关标签: 动态规划