题目链接
1987. 粉刷栅栏
农夫约翰发明了一种绝妙的方法来粉刷牛棚旁边的长栅栏(把栅栏想象成一维的数轴)。
他只需要在他最喜欢的奶牛贝茜身上挂一个刷子,然后在一旁悠闲的喝凉水就行了。
贝茜沿着栅栏来回走动时,会将她走过的栅栏部分涂上油漆。
贝茜从栅栏上的位置 \(0\) 处开始,共进行 \(N\) 次移动。
移动可能形如 10 L
,表示向左移动 \(10\) 单位距离,也可能形如 15 R
,表示向右移动 \(15\) 单位距离。
给定贝茜的 \(N\) 次移动列表,约翰想知道至少被涂抹了 \(2\) 层油漆的区域的总长度。
整个行进过程中,贝茜距离出发地的距离不会超过 \(10^9\)。
输入格式
第一行包含一个整数 \(N\)。
接下来 \(N\) 行,每一行包含一个行动指令,诸如 10 L
或 15 R
。
输出格式
输出至少被涂抹了 \(2\) 层油漆的区域的总长度。
数据范围
\(1≤N≤10^5\)
整个行进过程中,贝茜距离出发地的距离不会超过 \(10^9\)。
每次指令移动距离的取值范围是 \([1,2×10^9]\)。
输入样例:
6
2 R
6 L
1 R
8 L
1 R
2 R
输出样例:
6
样例解释
共有 \(6\) 单位长度的区域至少被涂抹 \(2\) 层油漆。
这些区域为 \((−11,−8),(−4,−3),(0,2)\)。
解题思路
差分,离散化,map
显然是一道差分+离散化模板题,这里用map
实现,离散化之后的区间都是权值连续的区间,即从开始到某个点的权值是相同的,从该点后面的点开始再到某个点又是另外一个权值是相同的 \(\dots\),需要注意这里求的是长度而不是点数
- 时间复杂度:\(O(nlogn)\)
代码
// Problem: 粉刷栅栏
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1989/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// %%%Skyqwq
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int main()
{
int n;
map<int,int> mp;
int pos=0;
for(scanf("%d",&n);n;n--)
{
int dis;
char op;
scanf("%d %c",&dis,&op);
if(op=='L')
{
mp[pos]--;
mp[pos-dis]++;
pos-=dis;
}
else
{
mp[pos]++;
mp[pos+dis]--;
pos+=dis;
}
}
int res=0,lst,sum=0;
for(auto [k,v]:mp)
{
if(sum>=2)res+=k-lst;
lst=k;
sum+=v;
}
printf("%d",res);
return 0;
}