目录
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
2、复杂度
3、代码详解
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
Problem - 1644E - Codeforces
二、解题报告
1、思路分析
很容易想明白被覆盖的面积,把最初的路径不断右移下移就能得到覆盖区域
一开始想着对路径上每个点可覆盖矩形求并,然后想到扫描线,想了想可以做,但还是去看下cf上的题解
然后发现只需要求贡献即可
cf上大佬给了张图,就拿着这个图来分析
对于只有D和R的情况直接返回n,就不说了
我们发现覆盖区域就是n * n 减去 白色区域,白色区域有两部分,右上角和左下角
右上角每一行白色来自D,左下角每一列白色,来自R
这里只讨论D的白色贡献,R的自然能类比
对于初始连续的前缀D,每一个D贡献是n - 1
对于剩下的D,我们发现其右边的白色长度取决于后面R的数目,那我们倒着遍历,计算R的数目,遇到D加上贡献就行了
2、复杂度
时间复杂度: O(Σlen(s))空间复杂度:O(len(s))
3、代码详解
#include <bits/stdc++.h>
using i64 = long long;
const int N = 2e5 + 10;
std::string s;
void solve(){
i64 n;
std::cin >> n >> s;
int len = s.size();
i64 res = 0;
int j = s.find('R');
if (j == -1) {
std::cout << n << '\n';
return;
}
res = j * (n - 1);
for(int i = len - 1, t = 0; i >= j; i --){
if(s[i] == 'D') res += t;
else t ++;
}
j = s.find('D');
if (j == -1) {
std::cout << n << '\n';
return;
}
res += j * (n - 1);
for(int i = len - 1, t = 0; i >= j; i --){
if(s[i] == 'R') res += t;
else t ++;
}
std::cout << n * n - res << '\n';
}
int main(){
int _ = 1;
std::cin >> _;
while(_ --)
solve();
return 0;
}