D. Priority Queue(Codeforces Round #729 (Div. 2))
D. Priority Queue
链接
题意
题意为给你n个操作模拟一个优先队列,其中 - 表示弹出队列中最小的元素,+ 表示向队列中加入一个整数x;
你可以任选操作,但相对顺序不能改变,对于每一个操作组合,求出最后队列中剩余数的和作为这个组合的最终结果,答案为所有操作组合的最终结果的和
思路
对于每个加入的数x
考虑其对答案的贡献,即求出其出现次数y
,则其对答案的贡献为x*y
对于当前下标i
(因为考虑贡献,所以忽略弹出操作),j
遍历所有下标,k
表示在1到j中小于a[i]
的数量(即子序列的长度),dp[j][k]
表示在上述情况下a[i]的出现次数。
转移情况如下:(a[i]表示第i次操作加入的元素,若为弹出操作则为-1)
dp的起始状态是:dp[0][0] = 1
基础转移方程:dp[j][k] = dp[j][k] + dp[j-1][k]
,因为1到j中小于a[i]的数量为k的出现次数一定来源于1到j-1中小于a[i]的数量为k的出现次数;当
a[j]==-1
时,dp[j][k] = dp[j][k] + dp[j-1][k+1]
;
如果i == j
,则直接跳过;
如果i != j
:如果
k == 0
的话,则dp[j][k] = dp[j][k] + dp[j-1][k]
;
如果a[j] < a[i]
,并且k != 0
,则dp[j][k] = dp[j][k] + dp[j-1][k-1]
;
如果a[j] == a[i]
,此时需要考虑j和i的关系,因为当大小相等时会按照相对顺序进行弹出,所以要保证j < i
,这样相当于a[j] < a[i]
的情况,所以仍是dp[j][k] = dp[j][k] + dp[j-1][k-1]
;
剩余情况(即a[j] > a[i]
或者a[j] == a[i] && j > i
),此时因为这类情况不会影响a[i]的出现,所以为:dp[j][k] = dp[j][k] + dp[j-1][k]
,相当于做了两遍基础转移方程,因为此时a[j]的选与不选在a[i]出现的情况下不会产生影响。
在每一轮结束后,更新答案,即加上此时a[i]的贡献(a[i] * y),y为出现次数,
Code
/*---------------------------------------------------------------
∧_∧
∧_∧ (´<_` )
( ´_ゝ`) / ⌒i
/ \ | |
/ / ̄ ̄ ̄ ̄/ |
__(__ニつ/ _/ .| .|____
\/____/ (u ⊃
--------------------------------------------------------------*/
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define fi first
#define se second
#define PI pair<int,int>
#define PII pair<ll,PI>
using namespace std;
typedef long long ll;
const int N=1e5+7;
const ll mod=998244353;
ll a[507];
ll dp[507][507];
int main()
{
IO;
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
{
char x;
cin >> x;
if (x == '-')
{
a[i] = -1;
}else{
cin >> a[i];
}
}ll ans = 0;
for (int i = 1; i <= n; ++i)
{
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
if (a[i] == -1)
{
continue;
}
for (int j = 1; j <= n; ++j)
{
for (int k = 0; k <= j; ++k)
{
dp[j][k] += dp[j-1][k];
dp[j][k] %= mod;
if (a[j] == -1)
{
dp[j][k] += dp[j-1][k+1];
dp[j][k] %= mod;
if (k == 0 && j < i)
{
dp[j][k] += dp[j-1][k];
dp[j][k] %= mod;
}
}
else{
if (i == j)
{
continue;
}
if (a[j] < a[i] || (a[j] == a[i] && j < i))
{
if (k != 0)
{
dp[j][k] += dp[j-1][k-1];
dp[j][k] %= mod;
}
}else {
dp[j][k] += dp[j-1][k];
dp[j][k] %= mod;
}
}
}
}
for (int j = 0; j <= n; ++j)
{
ans += a[i] * dp[n][j] % mod;
ans %= mod;
}
}cout << ans << endl;
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探秘 MySQL 索引底层原理,解锁数据库优化的关键密码(下)
· 大模型 Token 究竟是啥:图解大模型Token
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· BotSharp 5.0 MCP:迈向更开放的AI Agent框架
· 分享 3 款基于 .NET 开源且免费的远程桌面工具
· 在线聊天系统中的多窗口数据同步技术解密
· 2025,回顾出走的 10 年
· 【保姆级教程】windows 安装 docker 全流程