专栏文章

题解:CF2144E1 Looking at Towers (easy version)

CF2144E1题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minvzm58
此快照首次捕获于
2025/12/02 09:15
3 个月前
此快照最后确认于
2025/12/02 09:15
3 个月前
查看原文
  • E1 容易先处理出 L(a)L(a)R(a)R(a),设元素个数分别为 cntL,cntRcntL,cntR
接下来考虑 DP。设 dp1i,jdp1_{i,j} 表示前 ii 个数选了 LL 中的前 jj 个数的方案;dp2i,jdp2_{i,j} 表示后 ii 个数选了 RR 中的前 jj 个数的方案。两者方程相似,故下面只对 dp1dp1 进行讲解。
考虑转移,对于当前的数 aia_i,以及 LL 的前 jj 个数已经被选择,可以分为以下三种情况:
  • ai=Lja_i = L_jLjL_j 在之前已经被选择,则 aia_i 选不选均可,否则需要强制选,则有转移 dpi,j=2dpi1,j+dpi1,j1dp_{i,j} = 2dp_{i - 1,j} + dp_{i - 1,j - 1}
  • ai<Lja_i < L_j aia_i 的选择不会对 LL^\prime 造成影响,则有转移 dpi,j=2dpi1,jdp_{i,j} = 2dp_{i - 1,j}
  • ai>Lja_i > L_j 不能选择 aia_i,否则会破坏 L=LL = L^\prime,则有转移 dpi,j=dpi1,jdp_{i,j} = dp_{i - 1,j}
当统计答案时,需要小心重复计算的情况。因此当 aia_i 为全局最大值时,强制让 dp1dp1 去选择这个最大值,然后强制 dp2dp_2 不选这个最大值,则对答案的贡献为 (dp1i,cntLdp1i1,cntL)×dp2i+1,cntR1(dp1_{i,cntL} - dp1_{i - 1,cntL}) \times dp2_{i + 1,cntR - 1}
时间复杂度为 O(n2)O(n^2),代码如下:
CPP
void solve ()
{
    int n = read (),mx = 0;
    vector <int> a (n + 1),L (n + 1),R (n + 1);
    vector <vector <int>> dp1 (n + 1,vector <int> (n + 1)),dp2 (n + 2,vector <int> (n + 2));
    for (int i = 1;i <= n;++i) a[i] = read ();
    int cntL = 0,cntR = 0;
    for (int i = 1;i <= n;++i)
        if (mx < a[i]) L[++cntL] = a[i],mx = a[i];
    mx = 0;
    for (int i = n;i;--i)
        if (mx < a[i]) R[++cntR] = a[i],mx = a[i];
    dp1[0][0] = dp2[n + 1][0] = 1;
    for (int i = 1;i <= n;++i)
    {
        for (int j = cntL;~j;--j)
        {
            if (L[j] == a[i]) dp1[i][j] = (dp1[i - 1][j] * 2 % MOD + dp1[i - 1][j - 1]) % MOD;
            else if (L[j] > a[i]) dp1[i][j] = dp1[i - 1][j] * 2 % MOD;
            else dp1[i][j] = dp1[i - 1][j];
        }
    }
    for (int i = n;i >= 1;--i)
    {
        for (int j = cntR;~j;--j)
        {
            if (R[j] == a[i]) dp2[i][j] = (dp2[i + 1][j] * 2 % MOD + dp2[i + 1][j - 1]) % MOD;
            else if (R[j] > a[i]) dp2[i][j] = dp2[i + 1][j] * 2 % MOD;
            else dp2[i][j] = dp2[i + 1][j];
        }
    }
    ll ans = 0;
    for (int i = 1;i <= n;++i) 
    {
        if (a[i] != mx) continue;
        ans = (ans + 1ll * ((dp1[i][cntL] - dp1[i - 1][cntL] + MOD) % MOD) * dp2[i + 1][cntR - 1] % MOD) % MOD;
    }
    printf ("%lld\n",ans);
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...