CF1542D Priority Queue 題解
阿新 • • 發佈:2021-10-06
經過感性剖析,他顯然是個 $dp$
假定我們找到了處於位置 $t$ 的一個 $+x$ 設 $dp[i][j]$ 表示到第 $i$ 位為止,集合中有 $j$ 個數 $<=x$ 的方案數。
操作序列是陣列 $a$ ,我們的目的是要讓我們選定的這個到最後並對答案產生貢獻,我們分成以下幾種情況討論
當 $i<t$ 時
若這一位是 $-$ ,那麼 $dp[i][j] = dp[i-1][j] + dp[i-1][j+1]$ 如果不選,他就是上一位直接繼承下來
但如果選,他就相當於刪去了一個數,也就是說原來是 $j+1$
並且特別的,若 $ j=0 $ ,需要在上式的基礎上再加 $ dp[i-1][0] $
當 $ i=t $ 時
根據我們給的定義,這裡是必選的 $dp[i][j]=dp[i][j-1]$
當 $i>t$ 時
其實和 $i<t$ 差不多
若是 $-$ ,不存在特殊情況,因為此時我們找的那個 $x$ 已經在序列中了
若是 $+x$ 大於我們找的那個值
那麼 $dp[i][j]=dp[i-1][j]*2$
如果小於把 $j+1$ 就行了
最後統計答案
code:
#include <bits/stdc++.h> #define int long long using namespace std; int n,m; const int mod=998244353; const int maxn=610; struct node{ int x; bool plus;//判斷是哪種操作 }a[maxn]; int dp[maxn][maxn]; signed main() { cin>>n; int ans=0; for(int i=1;i<=n;i++) { char ch; cin>>ch; if(ch=='+') { a[i].plus=true; cin>>a[i].x; } else a[i].plus=false; } for(int t=1;t<=n;t++) { if(a[t].plus) { memset(dp,0,sizeof(dp));//每一次dp都要清零 int at=a[t].x; dp[0][0]=1;//初始狀態 for(int i=1;i<t;i++)//i<t的情況 { if(!a[i].plus)//如果第i位是- { for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j+1];//累加選的方案 dp[i][j]%=mod; } for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j];//累加不選的方案 dp[i][j]%=mod; } dp[i][0]=dp[i][0]+dp[i-1][0];//特殊情況 dp[i][0]%=mod; /* 這是因為會有兩種情況: 1. 根據題意,若沒有 $+x$ ,就不管他 2. 若刪去的數比 $x$ 大,也是 $dp[i-1][0]$ 所以要多加一遍 */ } else//如果第i位是+x { if(a[i].x>at) { for(int j=0;j<=n;j++) { dp[i][j]+=(dp[i-1][j]*2)%mod;//選與不選均不會對j有影響 dp[i][j]%=mod; } } else { for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j]%mod;//不選 dp[i][j]%=mod; } for(int j=1;j<=n;j++) { dp[i][j]+=dp[i-1][j-1]%mod;//選 dp[i][j]%=mod; } } } } for(int i=0;i<=n;i++)//i=t的情況 { dp[t][i]=dp[t-1][i]; } for(int i=t+1;i<=n;i++)//i>t的情況 { if(!a[i].plus) { for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j];//不選 dp[i][j]%=mod; } for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j+1];//選 dp[i][j]%=mod; } } else { if(a[i].x>=at) { for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j]*2%mod;//同上一種情況 dp[i][j]%=mod; } } else { for(int j=0;j<=n;j++) { dp[i][j]+=dp[i-1][j]%mod;//同上一種情況 dp[i][j]%=mod; } for(int j=1;j<=n;j++) { dp[i][j]+=dp[i-1][j-1]%mod; dp[i][j]%=mod; } } } } int tmp=0; for(int i=0;i<=n;i++)//計算總的貢獻 { tmp+=(dp[n][i]*a[t].x)%mod; tmp%=mod; } ans+=tmp; ans%=mod; } } cout<<ans; }