题目传送门
注意到数据很小只有 \(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;
}