(纪中)1746. 粉刷栅栏

57 篇文章 0 订阅

(File IO): input:paint.in output:paint.out
时间限制: 1000 ms 空间限制: 128001 KB 具体限制
Goto ProblemSet


题目描述
农夫约翰最近正在将他的栅栏粉刷一下(这里所有的栅栏都是在一条直线上的)。他是这样来粉刷的:他从位置 0 0 0出发,然后执行 N N N条指令,例如,指令可以是 “ 10 L ” “10 L” 10L,表示约翰从当前的位置向左移动 10 10 10个单位的距离,并且粉刷移动过程中遇到的栅栏,又或者是 “ 15 R ” “15 R” 15R,表示约翰从当前的位置向右移动 15 15 15个单位的距离,并且粉刷移动过程中遇到的栅栏。
给定所有约翰需要移动的指令,请计算所有栅栏中至少被粉刷两次的栅栏的总长度。约翰最多远离初始位置 1000000000 1000000000 1000000000个单位的距离。


输入
第一行一个正整数 N N N
接下来第 2 2 2行到第 N + 1 N+1 N+1行,每行表示每条指令。

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


样例输入
6

2 R

6 L

1 R

8 L

1 R

2 R

样例输出
6


数据范围限制
1<=N<=100000。


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


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


代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int x,ans,h,t,n;
string s;
char c;
struct cc{
	int x,y;
}a[150000];
bool cmp(const cc&l,const cc&r){
	return (l.x<r.x)||(l.x==r.x&&l.y<r.y);
}
int main(){
	freopen("paint.in","r",stdin);
    freopen("paint.out","w",stdout);
    int y;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
    	scanf("%d",&x);
    	cin>>c;
    	if(c=='R')
        x=y+x;
        else
        x=y-x;
		a[i].x=min(x,y);
		a[i].y=max(x,y);
		y=x;
	}
	sort(a+1,a+n+1,cmp);
	h=a[1].x; 
	t=a[1].y;
	for(int i=2;i<=n;i++)
	{
		if(a[i].y<h)continue;
		if(a[i].y<=t){
			ans=ans+a[i].y-max(a[i].x,h);
			h=a[i].y;
		}
		else if(a[i].x>t){
			h=a[i].x;
			t=a[i].y;
		}
		else if(a[i].x<h){
			ans=ans+t-h;
			h=t;
			t=a[i].y;
		}
		else{
			ans=ans+t-a[i].x;
        	h=t;
        	t=a[i].y;
	   }
	}
	cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值