1. 程式人生 > 其它 >普通DP——CF1542D Priority Queue

普通DP——CF1542D Priority Queue

普通DP——CF1542D Priority Queue

題目傳送門:Priority Queue

這道題目假如有長度為n,那麼子序列就有\(2^n\)個,如果按照n是500的資料範圍那麼肯定是回超時的。既然是算總和,我們只要對於這個序列中的每一個數到底有多少個序列包含了它(我們在這裡叫x)。這樣就可以算出這個數對答案的貢獻。

我們假設\(dp[i][j]\)的意思是在前i 個字串中選取的數中有j個數比x小(注意如果和x相同大,但是位置比x考前那麼也算進去)

然後思考轉移方程式:

  • 如果當前這個數字就是x,那麼\(dp[i][j] = dp[i-1][j]\)(一定是取這個數字,不然沒貢獻)
  • 如果當前這個數字小於x,或者和x相同大但是位置比x考前\(dp[i][j] = dp[i-1][j]+dp[i-1][j-1]\)
    (前面是不取,後面是取, ps:這裡要注意j為0的情況)
  • 如果當前這個數字大於x,或者和x相同大但是位置比x靠後\(dp[i][j] = dp[i-1][j]+dp[i-1][j]\)(前面這個是取,後面是不取)
  • 如果當前這個數字是符號,那麼我們再進行分類:
    • 如果當前j為0,那麼\(dp[i][0] = dp[i-1][1]+dp[i-1][0]+dp[i-1][j]\)(前兩個是取,後面是不取)
    • 如果當前j不是0,那麼\(dp[i][j] = dp[i-1][j+1]+dp[i-1][j]\)(前面是取,後面是不取)
#include<iostream>
#include<string>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int maxn = 505;
int dp[maxn][maxn];
int num[maxn];

void ini()
{
	memset(dp, 0, sizeof(dp));
	dp[0][0] = 1;
}
int main()
{
	int n;
	char ope;
	ll ans = 0;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++)
	{
		scanf(" %c", &ope);
		if(ope == '-') num[i] = -1;
		else  scanf("%d", &num[i]);
	}
	for(int i = 1; i <= n; i++)
	{
		if(num[i] == -1) continue;
		ini();
		for(int z = 1; z <= n; z++)
		{
			if(i == z)
			{
				for(int g = 0; g <= z; g++)
					dp[z][g] = dp[z-1][g];
			}
			else if(num[z] == -1) 
			{
				if(z < i) 
					dp[z][0] = (0ll + dp[z-1][0]*2 + dp[z-1][1])%mod;
				else 
					dp[z][0] = (0ll + dp[z-1][0]+dp[z-1][1])%mod;
				for(int g = 1; g <= z; g++)
				{
					dp[z][g] = (0ll + dp[z-1][g+1] + dp[z-1][g])%mod;
				}
					
			}
			else if(num[z] < num[i] || (num[z] == num[i] && z < i))
			{
				dp[z][0] = dp[z-1][0];
				for(int g = 1; g <= z; g++)
					dp[z][g] = (0ll + dp[z-1][g] + dp[z-1][g-1])%mod;
			}
			else
			{
				for(int g = 0; g <= z;g++)
					dp[z][g] = (2ll*dp[z-1][g])%mod;
			}
		}
		for(int g = 1; g <= n; g++)
			dp[n][g] = (dp[n][g] + dp[n][g-1])%mod;
		ans = (1ll*dp[n][n]*num[i] + ans)%mod;
	}
	printf("%lld", ans);
	return 0;
}