zoukankan      html  css  js  c++  java
  • CF1542D Priority Queue 题解

    一、题目:

    洛谷原题

    codeforces原题

    二、思路:

    这道题很明显是一道 DP 题。

    考虑计算某个 + x 对答案的贡献。也就是说,我们的目标是对于每个 + x,求出有多少个子序列满足经过一番操作之后,这个 (x) 会被统计到答案中。

    对于固定的、处于位置 (p) 的一个 + x,考虑 DP。设 (dp[i,j]) 表示考虑了前 (i) 位,有 (j) 个比 (x) 小的方案数。

    1. 若第 (i) 位是 -,则 (dp[i,j]=dp[i-1,j]+dp[i-1,j+1])

      这里需要着重强调,如果 (i<p)(j=0),那么 (dp[i,0]) 还要再加上 (dp[i-1,0])。原因是这样的,如果 (i<p),那么根据题目的约定,如果此时 (T) 是空的,那么我们什么也不做,所以,此时选上 - 号不会使得 (j) 变小。如果此时 (T) 中还有比 (x) 大的数,那 - 号也只会消去比 (x) 大的数,同样对 (j) 没有影响。

    2. 若第 (i) 位是正数而且比 (x) 大,则 (dp[i,j]=dp[i-1,j] imes 2)。选和不选都不会使得 (j) 改变。

    3. 若第 (i) 位是正数而且比 (x) 小,则

      [dp[i,j]= egin{cases} dp[i-1,j] &j=0\ dp[i-1,j]+dp[i-1,j-1] &j>0 end{cases} ]

    细心的同学可能会发现,那第 (i) 位如果和 (x) 相等怎么办?

    我的处理方法是这样的,为了避免重复计算,强制规定,如果 (i<p),那么就把它归到第 3 种情况中;如果 (i>p),那么就把它归到第 2 种情况中。

    三、代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    #define FILEIN(s) freopen(s, "r", stdin)
    #define FILEOUT(s) freopen(s, "w", stdout)
    #define mem(s, v) memset(s, v, sizeof s)
    
    inline int read(void) {
        int x = 0, f = 1; char ch = getchar();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
        return f * x;
    }
    
    const int MAXN = 505, MOD = 998244353;
    
    int n, a[MAXN];
    long long dp[MAXN][MAXN];
    
    int main() {
        n = read();
        for (int i = 1; i <= n; ++ i) {
            char op[3]; scanf("%s", op);
            if (*op == '-')
                a[i] = -1;
            else
                a[i] = read();
        }
        long long ans = 0;
        for (int p = 1; p <= n; ++ p) {
            if (a[p] < 0) continue;
            int x = a[p];
            mem(dp, 0); dp[0][0] = 1;
            for (int i = 1; i <= n; ++ i) {
                if (i == p) {
                    memcpy(dp[i], dp[i - 1], sizeof dp[i]);
                    continue;
                }
                for (int j = 0; j <= n; ++ j) {
                    if (a[i] < 0) {
                        dp[i][j] = (dp[i - 1][j] + dp[i - 1][j + 1]) % MOD;
                        if (j == 0 && i < p) (dp[i][j] += dp[i - 1][j]) %= MOD;
                    }
                    else if (a[i] < x || (a[i] == x && i < p)){
                        dp[i][j] = dp[i - 1][j];
                        if (j > 0) (dp[i][j] += dp[i - 1][j - 1]) %= MOD;
                    }
                    else
                        dp[i][j] = 2 * dp[i - 1][j] % MOD;
                }
            }
    
            long long sum = 0;
            for (int j = 0; j <= n; ++ j)
                (sum += dp[n][j]) %= MOD;
            (ans += sum * x % MOD) %= MOD;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    django 2.2, celery 4.3,出现 kombu.exceptions.EncodeError: cannot serialize '_io.BufferedReader' object 的分析解决
    python 算法
    zabbix--api学习之路--get_hostgroup获取
    zabbix-api学习之路--auth获取
    短链(ShortURL)的Java实现
    几种I/O模型功能和性能对比
    JMeter压测Rest请求
    git如何设置账号密码
    TCP和UDP之间的区别和联系
    Java BigDecimal和double
  • 原文地址:https://www.cnblogs.com/little-aztl/p/14968449.html
Copyright © 2011-2022 走看看