分析:
60分是因为用int会有溢出,
所以反正是为了AC,那么以后看到数据点超过10^5都可以直接用长长整型
还有对于只需要处理下一状态的数据的情况,可以考虑不使用数据结构存储输入的数据,直接在输入的时候就进行处理。
网上的答案我没能理解它的逻辑,所以还是按自己能搞清楚的逻辑写的。
remain_time是当前信号灯的剩余时间 减去 已经走过的时长。
大于0表示还在当前信号灯状态;
不大于0的时候,需要通过取模操作获取,此时remain_time是从当前信号灯的下一个状态的0时刻起
all_round = r + y + g
其实这一题,就是要看当前信号灯时长在经历sum_time后,到绿灯还要多久的时间
-
如果当前是红灯,时间区间就是绿 黄 红 [0, g) [g, g+y) [g+y, all_round)
那么只需要用 all_round - remain_time -
如果当前是黄灯,时间区间就是红 绿 黄 [0, r) [r, r+g) [r+g, all_round)
那么到绿灯 分两种情况
转换后为红灯 那么就是 r - remain_time
转换后为黄灯 则 all_round - remain_time + r -
如果当前是绿灯,时间区间 黄 红 绿 [0, y) [y, y+r) [y+r, all_round)
那么就是 y+r - remain_time
#include <bits/stdc++.h>
using namespace std;
void Handle();
typedef long long int ll;
int main() {
Handle();
return 0;
}
void Handle() {
ll r, y, g;
cin >> r >> y >> g;
ll all_round = r + y + g;
int n;
cin >> n;
int k;
ll t;
ll sum_time = 0;
ll remain_time = 0;
for (int i = 0; i < n; i++)
{
cin >> k >> t;
switch (k)
{
case 0:
sum_time += t;
break;
case 1: //红灯
remain_time = t - sum_time;
if (remain_time <= 0) //需要进行红绿灯状态转换
{
remain_time = abs(remain_time) % all_round;
if (remain_time >= g && remain_time < all_round)
sum_time += all_round - remain_time;
}
else
sum_time += remain_time;
break;
case 2: //黄灯
remain_time = t - sum_time;
if (remain_time <= 0)
{
remain_time = abs(remain_time) % all_round;
if (remain_time >= 0 && remain_time < r) //转换后为红灯
sum_time += r - remain_time;
else if (remain_time >= r+g && remain_time < all_round) //转换后为黄灯
sum_time += all_round - remain_time + r;
}
else
sum_time += remain_time + r;
break;
case 3: //绿灯
remain_time = t - sum_time;
if (remain_time <= 0)
{
remain_time = abs(remain_time) % all_round;
if (remain_time >= 0 && remain_time < y + r) //转换后为红灯或黄灯
sum_time += y + r - remain_time;
}
break;
default:
break;
}
}
cout << sum_time;
}