2020.02.13普及C组模拟赛6(第三题)

3.粉刷栅栏

题目描述

题目:

农夫约翰最近正在将他的栅栏粉刷一下(这里所有的栅栏都是在一条直线上的)。他是这样来粉刷的:他从位置0出发,然后执行N条指令,例如,指令可以是“10 L”,表示约翰从当前的位置向左移动10个单位的距离,并且粉刷移动过程中遇到的栅栏,又或者是“15 R”,表示约翰从当前的位置向右移动15个单位的距离,并且粉刷移动过程中遇到的栅栏。

问题描述:

给定所有约翰需要移动的指令,请计算所有栅栏中至少被粉刷两次的栅栏的总长度。约翰最多远离初始位置1000000000个单位的距离。

输入

第一行一个正整数N。

接下来第2行到第N+1行,每行表示每条指令。

输出

只有一行一个整数,表示所有栅栏中至少被粉刷两次的栅栏的总长度。

样例输入

6

2 R

6 L

1 R

8 L

1 R

2 R

样例输出

6

数据范围限制

数据范围:1<=N<=100000。

提示

说明:样例中,有6个单位的长度至少被粉刷两次。分别是[-11,-8],[-4,-3],[0,2]。

正解
把每一次的操作变成一个区间,存区间的右端和左端。
按照从小到大的顺序快排
然后纯模拟五种情况分类讨论。
AC代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,x,o,head,tail,s;
char ch;
struct stu
{
	int head,tail;
}a[100005];
bool cmp(stu x,stu y)//快排
{
	if(x.head==y.head)return x.tail<y.tail;
	return x.head<y.head;
}
int main()
{
	freopen("paint.in","r",stdin);
	freopen("paint.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>x>>ch;
		if(ch=='R')//下面是区间存储
		{
			a[i].head=o;
			a[i].tail=o+x;
			o+=x;
		}
		else
		{
			a[i].tail=o;
			a[i].head=o-x;
			o-=x;
		}
	}
	sort(a+1,a+n+1,cmp);
	head=a[1].head;
	tail=a[1].tail;
	for(int i=2;i<=n;i++)//下面是区间模拟
	{
		x=0;
		if(a[i].tail<=head)x=1;
		if(a[i].tail<=tail&&x==0)
		{
			s+=a[i].tail-max(a[i].head,head);
			head=a[i].tail;
			x=1;
		}
		if(a[i].head>=tail&&x==0)
		{
			head=a[i].head;
			tail=a[i].tail;
			x=1;
		}
		if(a[i].head<=head&&x==0)
		{
			s+=tail-head;
			head=tail;
			tail=a[i].tail;
			x=1;
		}
		if(x==0)
		{
			s+=tail-a[i].head;
			head=tail;
			tail=a[i].tail;
		}
	}
	cout<<s;
	return 0;
}

下面附本次比赛的其他题目

2020.02.13普及C组模拟赛6(第一题)
2020.02.13普及C组模拟赛6(第二题)
2020.02.13普及C组模拟赛6(第三题)
2020.02.13普及C组模拟赛6(第四题)
2020.02.13普及C组模拟赛6(总结)

谢谢观看

发布了65 篇原创文章 · 获赞 93 · 访问量 1845

猜你喜欢

转载自blog.csdn.net/weixin_45524309/article/details/104543182