首页 > 技术文章 > 洛谷 P5269 欧稳欧再次学车 题解

acioi 2019-11-06 17:21 原文

P5269 欧稳欧再次学车

题目背景

请自行脑补一张欧稳欧学车的图

题目描述

欧稳欧学车时经常用一辆橡树车练习。这辆橡树车共有 \(N\) 个挡位,欧稳欧每秒可以把挡位增加或减少 \(1\),初始时(\(0\) 时刻)挡位为 $ 1$。

这辆车的转速范围是 \([L,R]\),初始时转速为 $ L$。每次升挡时,转速会变成 \(L\);降挡时,会变成 \(R\)。欧稳欧在每秒也可以踩油门,让转速增加 \(X\),再对 \(R\)\(\text{min}\)。如果转速连续 \(K\) 秒都 \(=R\),那么这辆车的发动机会停止工作,在这 \(K\) 秒结束的一瞬间停下(即使 \(K\) 秒中经历了降档操作,仍然算这种情况)。

这些操作我们认为都是在每秒开头的一瞬间进行的,其中换挡操作比踩油门操作先进行。而这一秒内这辆车前进的距离是 转速\(\times\)挡位。

现在给出欧稳欧练习时的操作序列,你需要求出他一共前进的距离是多少。

输入格式

第一行六个整数 \(T,N,L,R,X,K\)\(T\) 表示总时间。

接下来 \(T\) 行,每行两个整数 \(x,y\),表示这一秒的操作。

其中 \(x=0\) 表示升挡,\(x=1\) 表示降挡,\(x=2\) 表示挡位不变;\(y=0\) 表示不踩油门,\(y=1\) 表示踩油门。(不要问为什么没有刹车)

输出格式

一行一个整数,表示给定操作序列的前进距离。

如果欧稳欧在挡位为 \(N\) 时升挡,或在挡位为 \(1\) 时降挡,那么给定序列不合法,输出 \(-1\)

输入输出样例

输入 #1

5 3 1 10 5 100
0 1
0 0
2 1
2 1
1 1

输出 #1

83

输入 #2

3 1 1 1 1 2
2 0
2 1
2 0

输出 #2

2

输入 #3

1 2 3 4 5 6
1 0

输出 #3

-1

说明/提示

对于样例一:

第一秒挡位为 \(2\),转速为 \(6\)
第二秒挡位为 \(3\),转速为 \(1\)
第三秒挡位为 \(3\),转速为 \(6\)
第四秒挡位为 \(3\),转速为 \(10\)
第五秒挡位为 \(2\),转速为 \(10\)

对于样例二,前进两秒之后发动机就停止了工作。

对于 \(30\%\) 的数据,没有挡位操作(即保证 \(x=2\));

对于另外 \(30\%\) 的数据,没有踩油门操作(即保证 \(y=0\));

对于全部数据,保证 \(1\le T,N,L,R,X,K\le 10^6,L\le R\)

【思路】

模拟

【说在前面的话】

其实很简单的我想复杂了
所以看了很久的题目,担心写出锅
主要原因还是因为这道题是gyh大佬给我推荐的
大佬推荐的当然简单不了啦
不过没想到gyh这么体贴我这个蒟蒻
找适合我这个水平的题目来给我做
开心qwq
(为什么不开long long 只有10分,这不对)

【题目分析】

关于档位有三个操作,关于速度有两个操作
升档,降档,不动和加速,不加速
根据给出的数据来模拟就好了

【核心思路】

根据提议来模拟就好了
先判断是升档,降档还是不动
如果是升档那就让档位增加,速度变为l
如果是降档那就让档位减少,速度变为r
如果是不动那就是不用管了

在判断是加速还是不加速
加速那就用现在速度加上x之后和r取min
不加速就不用管

还有会不会抛锚这也是一个问题
只需要开一个变量储存已经在r速度上面持续了多久
如果这个时候速度是r那就变量++
不然就要变为0

【完整代码】

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;

int read()
{
	int sum = 0,fg = 1;
	char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-')fg = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		sum = sum * 10 + c - '0';
		c = getchar();
	}
	return sum * fg;
}

signed main()
{
	int ans = 0;
	int t = read(),n = read(),l = read(),r = read(),x = read(),k = read();
	int dang = 1,zhuan = l;
	int last = 0;
	for(register int i = 1;i <= t;++ i)
	{
		int opt = read(),y = read();
		if(opt == 0)//升档 
		{
			if(dang == n)
			{
				cout << -1 << endl;
				return 0;
			}
			dang ++;
			zhuan = l;//先升档
			//如果不踩油门,那就只处理升档,如果踩油门那就加速 
			if(y == 1)
				zhuan = min(r,zhuan + x); 
		}
		else
		if(opt == 1)//降档 
		{
			if(dang == 1)
			{
				cout << -1 << endl;
				return 0;
			}
			dang --;
			zhuan = r;
			if(y == 1)
				zhuan = min(r,zhuan + x);
		}
		else//档位不变 
		{
			if(y == 1)
				zhuan = min(r,zhuan + x);
		}
		ans += zhuan * dang;
		if(zhuan == r)
			last ++;
		else
			last = 0;
		if(last == k)
			break;
	}
	cout << ans << endl;
	return 0;
}
/*
6 3 1 10 5 100
0 1
0 0
2 1
2 1
1 1
1 0
*/

推荐阅读