随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3251

一、题目描述

  给定一个序列 AA 的每一个元素形如 +x 和 ,其中 x 为一个整数(1x<998244353)。

  对于 A 的一个子序列 S,按如下方式计算 S 的权值:

    你需要依次遍历 S 中的元素,并且按照序列维护一个小根堆 T

    特别的,若 T 中没有数,那么就不进行删除操作。

    在遍历完 S 中的元素后,将小根堆 T 中所有数的和 sum 算出来。

    sum 即为 S 的权值。

  求 A 中所有子序列 S 的权值和。对 998244353 取模。

  数据范围:1n500


 二、解题思路:

  掌握一个算贡献的方法:AxA=xx×A[xA]

  于是我们可以很容易的想到单独对于每个 +x 统计贡献。

  然后这个是非常容易计数 dp 的,设目前我们枚举的位置为 p。值为 val

  fi,j 表示目前枚举到序列的前 i 个元素,小根堆中有 j 个数字小于 val 的子序列个数。

  转移很好转移,注意 ip 的相对位置来进行讨论。

  相同的数字大小关系定一个标准就行了,比如下标小的就视为更小。

  单次 dp 时间复杂度 O(n2),总时间复杂度 O(n3)


 三、完整代码

复制代码
 1 #include<iostream>
 2 #define N 510
 3 #define mod 998244353
 4 #define ll long long
 5 #define rep(i,l,r) for(ll i=l;i<=r;i++)
 6 using namespace std;
 7 ll n,ans;
 8 ll f[N][N];
 9 ll op[N],a[N];
10 void add(ll &u,ll v){
11     u+=v;
12     if(u>=mod) u%=mod;
13 }
14 ll calc(ll p){
15     ll val=a[p]; f[0][0]=1;
16     rep(i,1,n) rep(j,0,i) f[i][j]=0;
17     rep(i,1,n){
18         rep(j,0,i) f[i][j]=f[i-1][j];
19         if(i<p){    
20             if(!op[i]){
21                 rep(j,0,i) add(f[i][j],f[i-1][j+1]);
22                 add(f[i][0],f[i-1][0]);
23             }else{
24                 if(a[i]>val){
25                     rep(j,0,i) add(f[i][j],f[i-1][j]);
26                 }else{
27                     rep(j,1,i) add(f[i][j],f[i-1][j-1]);
28                 }
29             }
30         }else if(i>p){
31             if(!op[i]){
32                 rep(j,0,i) add(f[i][j],f[i-1][j+1]);
33             }else{
34                 if(a[i]>=val){
35                     rep(j,0,i) add(f[i][j],f[i-1][j]);
36                 }else{
37                     rep(j,1,i) add(f[i][j],f[i-1][j-1]);
38                 }
39             }
40         }
41     }
42     ll res=0;
43     rep(i,0,n) add(res,f[n][i]);
44     return res;
45 }
46 signed main(){
47     ios::sync_with_stdio(false);
48     cin.tie(0); cout.tie(0);
49     cin>>n;
50     rep(i,1,n){
51         char x; cin>>x;
52         if(x=='+') op[i]=1,cin>>a[i];
53     }
54     rep(i,1,n) if(op[i]) add(ans,calc(i)*a[i]);
55     cout<<ans<<'\n';
56     return 0;
57 }
复制代码

四、写题心得:

  复竞了,感觉手好生。只有写点简单题找一下感觉了。

  不过这个题还是很有意思啊!拜谢 lsy 大佬。省选加油!

posted on   trh0630  阅读(20)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示