CF1542D - Priority Queue(dp,贡献单独处理)
题目
题解
直接计算似乎十分困难,那么可以单独考虑每个数x的贡献。\(B_x\)为最后\(x\)存在于队列中的方案数,那么答案就是\(\sum{x\times B_x}\)。
对于每条类型2的指令I,假设它的值为X,它的方案数可以用dp计算得到。令dp[i][j]代表在第i条指令时队列内比X小的数有j个时的方案数。在比较大小时用位置作为第二关键字,再特判i==I时的转移方程,这样就只有大于和小于两种情况,不会算漏。
细节详见代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
const int N = 510;
const int M = 998244353;
ll dp[N][N];
ll arr[N];
bool flag[N];
int main() {
IOS;
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
char ch;
cin >> ch;
if(ch == '-') {
flag[i] = true;
} else {
cin >> arr[i];
}
}
ll ans = 0;
for(int I = 1; I <= n; I++) {
if(flag[I]) continue;
memset(dp, 0, sizeof dp);
dp[0][0] = 1;
ll V = arr[I];
for(int i = 1; i <= n; i++) {
if(flag[i]) {
for(int j = 0; j <= i; j++) {
dp[i][j] = (dp[i - 1][j] + dp[i - 1][j + 1]) % M;
if(j == 0) dp[i][j] += dp[i - 1][j];
dp[i][j] %= M;
}
} else if(i == I) {
for(int j = 0; j <= i; j++) {
if(j - 1 >= 0) dp[i][j] = dp[i - 1][j - 1];
}
} else if(i < I){
if(arr[i] <= V) {
for(int j = 0; j <= i; j++) {
dp[i][j] = dp[i - 1][j];
if(j - 1 >= 0) dp[i][j] += dp[i - 1][j - 1];
dp[i][j] %= M;
}
} else {
for(int j = 0; j <= i; j++) {
dp[i][j] = 2 * dp[i - 1][j] % M;
}
}
} else {
if(arr[i] < V) {
for(int j = 0; j <= i; j++) {
dp[i][j] = dp[i - 1][j];
if(j - 1 > 0) dp[i][j] += dp[i - 1][j - 1];
dp[i][j] %= M;
}
} else {
for(int j = 0; j <= i; j++) {
dp[i][j] = 2 * dp[i - 1][j] % M;
}
}
}
}
for(int i = 1; i <= n; i++) {
ans += V * dp[n][i] % M;
ans %= M;
}
}
cout << ans << endl;
}