Java教程

1987. 粉刷栅栏

本文主要是介绍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;
}
这篇关于1987. 粉刷栅栏的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!