2018 Zhejiang Province Competition Bracket Sequence

meaning of the title

You have n elements arranged in a row, each element consists of a parenthesis (left or right parenthesis) and a weight, we denote the i-th element as (si; vi), where si is "(" or ")", vi is an integer (may be negative).

You can select a pair of adjacent elements each time, and the corresponding brackets are "()", that is, find a k(1 k < n) that satisfies sk as "(" and sk+1 as ")". You can swap the k and k + 1 elements (including the brackets and corresponding weights) and get a score of vk vk+1.

Now give you the initial arrangement of elements and ask how many points you can get.


If all numbers are > 0, then greedily move all ) to the far left, but there are negative numbers here.

First to find

1. The answer depends only on the original state and the final state [can be sure that each ')' spans several '(']

2. The right parenthesis to the right of a closing parenthesis in the original sequence cannot cross it when it is shifted to the left

So dp[i][j] means that when it reaches the i-th ')' from the left, it will finally be placed after the j-th '(', what is the maximum profit

It seems to enumerate dp[i-1][k](0<=k<=j) and find that each transfer is dp[i-1],[0-j]+v[j--current '(' number], this can maintain the prefix maximum value and the prefix sum and optimize it to reduce the dp transfer to O(1)

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
char s[2020];
LL dp[2020][2020],A[2020],sum[2200];
int len, n, m;
LL Max(LL a,LL b){
	if (a>b) return a;
	return b;
}
void Work(){
	memset(sum,0,sizeof(sum));
	n=m=0;
	int i,j,mz=0;
	scanf("%d",&len);
	for (i=1;i<=len;i++){
		cin>>s[i];
		if (s[i]=='(') mz++;
	}
	for (i=1;i<=len;i++)
		scanf("%lld",&A[i]);
	
	for (i=1;i<=len;i++){
		if (s[i]=='('){
			m++;
			sum[m]=sum[m-1]+A[i];
			continue;
		}
		n++;
		for (j=0;j<=m;j++){
			dp[n][j]=dp[n-1][j]+(sum[m]-sum[j])*A[i];
			if (j) dp[n][j]=Max(dp[n][j],dp[n][j-1]);
		}
		for (j=m+1;j<=mz;j++) dp[n][j]=dp[n][j-1];//The transfer will be used later
	}
	cout<<dp[n][m]<<endl;
}
int main(){
	int num; cin>>num;
	while (num--) Work();
}

dp[i][j] is only transferred from dp[i-1][j]. Although the space of this question does not need to be optimized, we find that one dimension can be optimized away. In this case, the dp array needs to be initialized

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
char s[2020];
LL dp[2020],A[2020],sum[2200];
int len, n, m;
LL Max(LL a,LL b){
	if (a>b) return a;
	return b;
}
void Work(){
	memset(sum,0,sizeof(sum));
	memset(dp,0,sizeof(dp));
	n=m=0;
	int i,j,mz=0;
	scanf("%d",&len);
	for (i=1;i<=len;i++){
		cin>>s[i];
		if (s[i]=='(') mz++;
	}
	for (i=1;i<=len;i++)
		scanf("%lld",&A[i]);
	
	for (i=1;i<=len;i++){
		if (s[i]=='('){
			m++;
			sum[m]=sum[m-1]+A[i];
			continue;
		}
		n++;
		for (j=0;j<=m;j++){
			dp[j]=dp[j]+(sum[m]-sum[j])*A[i];
			if (j) dp[j]=Max(dp[j],dp[j-1]);
		}
		for (j=m+1;j<=mz;j++) dp[j]=dp[j-1];
	}
	cout<<dp[m]<<endl;
}
int main(){
	int num; cin>>num;
	while (num--) Work();
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325935635&siteId=291194637