题解: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;
}

posted @ 2025-09-10 21:36  一班的hoko  阅读(5)  评论(0)    收藏  举报