老夫聊发少年狂,碱金属,丢池塘。浮溶游响,激起千朵|

Yaosicheng124

园龄:1年3个月粉丝:8关注:11

CF 1913 D

题目描述

给定一个所有数互不相同的长度为 N 的序列 P,你可以执行以下操作任意次:

  • 选择一对 1l<rN,并把其中除最小值外的所有元素删除。

求最终可以得到的不同序列数量。

思路

我们考虑怎样通过删除最少的元素来删除 i,很明显,就是选择区间 [l,i][i,r],这里 l 是最大的满足 l<iPl<Pi 的下标,而 r 是最小的满足 r>iPr<Pi 的下标。这个可以使用单调栈求出。

我们每次都只删除这种最小区间,因为这样会使最终的方案更多。

dp0/1,i 表示考虑前 i 个数,最后一个数选/不选的种类数。

我们有 dp0,idp0/1,li(因为没有任何影响,随便怎么选,但如果不删除 i,那么 li+1i 都无法删除)。以及 dp1,idp1,j(lij<i),dp0,li,因为删掉 i 就意味着删掉 li+1i,而 li 是既可以删也可以不删。这个可以使用前缀和优化。

时空复杂度均为 O(N)

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 300001, MOD = 998244353;

int t, n, a[MAXN], stk[MAXN], top, dp[2][MAXN], sum[MAXN];

void Solve() {
  cin >> n;
  for(int i = 1; i <= n; ++i) {
    cin >> a[i];
  }
  top = 0;
  dp[1][0] = sum[0] = 1;
  for(int i = 1; i <= n; ++i) {
    for(; top && a[stk[top]] >= a[i]; --top) {
    }
    int j = stk[top];
    dp[0][i] = (j ? (dp[1][j] + dp[0][j]) % MOD : 0);
    dp[1][i] = (0ll + dp[0][j] + sum[i - 1] - (j ? sum[j - 1] : 0) + MOD) % MOD;
    sum[i] = (sum[i - 1] + dp[1][i]) % MOD;
    stk[++top] = i;
  }
  cout << (dp[0][n] + dp[1][n]) % MOD << "\n";
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  for(cin >> t; t--; Solve()) {
  }
  return 0;
}

本文作者:Yaosicheng124

本文链接:https://www.cnblogs.com/yaosicheng124/p/18417352

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Yaosicheng124  阅读(5)  评论(0编辑  收藏  举报
  1. 1 Minecraft C418
Minecraft - C418
00:00 / 00:00
An audio error has occurred.

暂无歌词

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起