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$。
- 有 $H-1 - (\text{原本的 D})$ 个
-
✅ 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;
} 
浙公网安备 33010602011771号