ARC 197 A个人题解

ARC197 div2 A 题解:路径数量统计

前情提要

初看的时候没有一点思路,但其实本题非常适合分类讨论 + 区间统计处理。推荐一步步分析,思路清晰后代码实现非常简洁。


    • 🧩 核心想法拆解(Step by Step)

      ✅ Hit 1:路径中 D 和 R 的数量固定

      目标是从 $(1,1)$ 走到 $(H,W)$,即必须恰好走 $H-1$ 次 D 和 $W-1$ 次 R

      假设有 $K$ 个 ? 被替换成 D,那就是:

      • 有 $H-1 - (\text{原本的 D})$ 个 ? 替换成 D
      • 剩下的 ? 替换成 R

      ✅ Hit 2:按步数 $k$ 划分

      走完 $k$ 步后,下移次数 $d$ 的 前缀约束

      ​ $[
      d \in [\mathrm{prefD}[k],;\mathrm{prefD}[k]+\mathrm{prefQ}[k]]
      ]$


      ✅ Hit 3:后缀能够补齐剩余的 D

      还剩下 $(H-1)-d$ 个 D 要用后缀中的 ? 补齐,得到 后缀约束
      $[
      d \in \bigl[H-1 - (\mathrm{suffD}[k+1]+\mathrm{suffQ}[k+1]),;H-1-\mathrm{suffD}[k+1]\bigr]
      ]$


      ✅ Hit 4:边界条件

      • 下移总数 $\le H-1$

      • 右移总数 $\le W-1 ;\Longrightarrow; d \ge k-(W-1)$

        合并成:
        $[
        d \in [,k-(W-1),;H-1,].
        ]$


      🔍 合并三类区间

      对每个 $k\in[0,,H+W-2]$,取交集:
      $[
      d \in
      \Bigl[
      \max\bigl(\mathrm{prefD}[k],;k-(W-1),;H-1-(\mathrm{suffD}[k+1]+\mathrm{suffQ}[k+1])\bigr),;
      \min\bigl(\mathrm{prefD}[k]+\mathrm{prefQ}[k],;H-1,;H-1-\mathrm{suffD}[k+1]\bigr)
      \Bigr].
      ]$
      只要下界 $\le$ 上界,就贡献上界-下界+1 个格子。


      🧮 时间复杂度

      总共两次前后缀扫描 + 一次 $k$ 枚举,都是 $O(H+W)$,合并后也在 $O(H+W)$,满足 $\sum(H+W)\le4\times10^5$。



✅ C++ 实现

Code (C++)
/*
别水群了哥
别打游戏了哥
别看番了哥
*/
#include  //曼哈顿转切比雪夫->x+y,x-y
using namespace std;     // 切比雪夫转曼哈顿(x+y)/2,(x-y)/2
const int mod = 998244353;
const int N = 200005;
const int inf = 0x3f3f3f;
typedef long long ll;
using pii = pair;
auto vec(int D) { return std::vector(D); }
template 
auto vec(int D, R... r) { return std::vector(D, vec(r...)); } // auto dp =vec(a,b,c);
struct node
{
    int x, y, d, ans;
    /* data */
};
void graspppp()
{
    int H, W;
    string s;
    cin >> H >> W >> s;
    int l = H + W - 2;
    vector pred(l + 1, 0), preq(l + 1, 0);
    vector sufd(l + 2, 0), sufq(l + 2, 0);
    for (int i = 1; i <= l; i++)
    {
        pred[i] = pred[i - 1] + (s[i-1] == 'D');
        preq[i] = preq[i - 1] + (s[i-1] == '?');
    }
    for (int i = l; i >= 1; i--)
    {
        sufd[i] = sufd[i + 1] + (s[i-1] == 'D');
        sufq[i] = sufq[i + 1] + (s[i-1] == '?');
    }
    ll ans = 0;
    for (int k = 0; k <= l; k++)
    {
        int lo = max({pred[k], k - (W - 1), (H - 1) - (sufd[k + 1] + sufq[k + 1])});
        int hi = min({pred[k] + preq[k], H - 1, H - 1 - sufd[k + 1]});
        if (hi >= lo)
            ans += hi - lo + 1;
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--)
        graspppp();
    return 0;
}
posted @ 2025-05-29 11:43  graspppp  阅读(27)  评论(0)    收藏  举报