1987. 粉刷栅栏

题目链接

1987. 粉刷栅栏

农夫约翰发明了一种绝妙的方法来粉刷牛棚旁边的长栅栏(把栅栏想象成一维的数轴)。

他只需要在他最喜欢的奶牛贝茜身上挂一个刷子,然后在一旁悠闲的喝凉水就行了。

贝茜沿着栅栏来回走动时,会将她走过的栅栏部分涂上油漆。

贝茜从栅栏上的位置 \(0\) 处开始,共进行 \(N\) 次移动。

移动可能形如 10 L,表示向左移动 \(10\) 单位距离,也可能形如 15 R,表示向右移动 \(15\) 单位距离。

给定贝茜的 \(N\) 次移动列表,约翰想知道至少被涂抹了 \(2\) 层油漆的区域的总长度。

整个行进过程中,贝茜距离出发地的距离不会超过 \(10^9\)。

输入格式

第一行包含一个整数 \(N\)。

接下来 \(N\) 行,每一行包含一个行动指令,诸如 10 L15 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;
}
上一篇:【C++】STL容器之string


下一篇:string容器