思路:红绿灯是有周期性的,所以可以用
【(到达某个红绿灯时所用时间--去当前红绿灯所剩时间)+ (r或者r+g)】%(红灯、绿灯、黄灯持续时间总和)
来找到到达某个红绿灯时该红绿灯的颜色,最后对应计算即可。
注意(r或者r+g)的分别,当出发时该红绿灯是红色就+r,是绿色就+r+g,如果是黄灯就不用加,因为算周期时会变成零点
步骤:
- 红绿灯的周期性:
- 红绿灯的变化是周期性的,每个周期由红、黄、绿三种灯组成,每种灯持续的时间可能不同。
- 通过计算红黄绿三种灯的总时间,可以得到一个完整的周期长度。
- 计算特定时间点对应的灯状态:
- 给定一个时间点,需要确定这个时间点对应的灯是什么颜色。这通常涉及到将时间点对周期长度取余,然后根据余数确定灯的状态。
- 处理询问:
- 对于每个询问,首先判断是否是红绿灯状态。如果不是,则直接累加时间点。
- 如果是红绿灯状态,需要判断询问的时间点是否对应当前的灯。如果是,根据灯的颜色决定是否累加等待时间。
- 如果询问的时间点不对应当前的灯,则需要计算从询问时间点开始到下一个目标灯状态所需的时间,并累加到总等待时间中。
//一定要注意因为n比较大,那么所有与ans有关的都必须要用long long ----*********做完题提交之间,一定要判断一下是否需要使用 long long 另外,一定要严谨,与大数有关的都要用long long
#include<iostream>
using namespace std;
int n;
int r,y,g;
long long fun(int k,long long tp){ //因为找周期时起点不一定是零点,有可能是红变绿 绿变黄的点,所以周期找余时,一定要把起点算上
if(k==1){
return tp+r;
}
else if(k==2){
return tp;
}
else if(k==3){
return tp+r+g;
}
}
int main(){
cin>>r>>y>>g;
cin>>n;
long long ans=0;
int sum1=r+g+y;
for(int i=0;i<n;i++){
int k,t;
cin>>k>>t;
if(k==0){
ans+=t;
}
else{//遇到红绿灯
if((ans-t)<0){//灯即为当前的灯
if(k==3){ //遇到了绿灯
continue;
}
else if(k==1) //遇到了红灯
{
ans+=t;
}
else if(k==2){ //遇到了黄灯
ans+=t;
ans+=r;
}
}
else{//灯不是现在的灯,要循环
long long temp2=fun(k,ans-t); //因为绿色要额外加r+g,那么就有可能超出了周期,所以要先加然后再求余
int temp=(temp2)%sum1;
if(temp>=0&&temp<r){ //红
ans+=(r-temp);
}
else if(temp>=r&&temp<r+g){//绿
continue;
}
else if(temp>=r+g&&temp<r+g+y){//黄
ans+=(r+g+y-temp+r);
}
}
}
}
cout<<ans;
return 0;
}