题解:CF2118D1 Red Light, Green Light (Easy version)
题目传送门
注意到数据很小只有 \(500\),所以想到可以模拟加记忆化,每一次暴力的去找到下一个要到的红绿灯的编号,再判断是红灯还是绿灯,如果是绿灯那方向不变,编号根据方向判定是加一还是减一,若果是红灯那方向改变,编号同理,同时用数组记录一下这一次遇到红灯的状态,三个状态分别为:编号,方向和时间,如果在模拟过程中编号小于 \(1\) 或编号大于 \(n\) 那么说明可以走出去,若果两次走到同一个状态,那么就不可能走出去。
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1010101;
ll n,k,T,x,q,p[N],d[N],vis[510][3][510];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++)cin>>d[i];
cin>>q;
while(q--){
cin>>x;
memset(vis,0,sizeof(vis));
ll cnt=0,flag=1,now=0;
for(int i=1;i<=n;i++){
if(p[i]>=x){
now=i;
break;
}
}
if(now==0){
cout<<"YES\n";
continue;
}
while(1){
if((cnt+abs(p[now]-x)-d[now])%k!=0){
cnt+=abs(p[now]-x);
x=p[now];
if(flag)now++;
else now--;
if(now>n||now<1){
cout<<"YES\n";
break;
}
}else{
if(vis[now][flag][(cnt+abs(p[now]-x)-d[now])%k]){
cout<<"NO\n";
break;
}
vis[now][flag][(cnt+abs(p[now]-x)-d[now])%k]=1;
cnt+=abs(p[now]-x);
x=p[now];
if(flag)now--;
else now++;
if(now>n||now<1){
cout<<"YES\n";
break;
}
flag^=1;
}
}
}
}
return 0;
}

浙公网安备 33010602011771号