This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll S;
struct State{
    ll a1, d1, a2, d2;
    bool operator==(const State& other) const {return a1==other.a1 && a2 == other.a2 && d1 == other.d1 && d2 == other.d2;}
};
State sab(State state){
    return {state.a2, max(0ll, state.d2 - 1), state.a1, state.d1};
}
State att(State state){
    return {state.a2 - (state.a1 - S*state.d2), state.d2, state.a1, state.d1};
}
vector<vector<vector<int>>> dp;
bool half_sab_win(State state){
    ll sab_cnt = state.d2 / 2;
    state.a1 -= sab_cnt * (state.a2 - S*state.d1);
    state.d2 -= sab_cnt;
    state = att(state);
    state.a1 -= state.d2 * (state.a2 - S*state.d1);
    state.d2 = 0;
    state = att(state);
    ll alpha1 = state.a1 - S*state.d2;
    ll beta2 = S - state.a2;
    return alpha1 + state.d2 * beta2 >= S;
}
ll calc(ll d1, ll d2, ll a2);
int calls = 0;
bool wins(State state){
    // trivial cases
    if(state.a1 <= 0) return false;
    if(state.a2 <= 0) return true;
    // no one can attack
    ll sab_rounds = (max(0ll, min(state.d2*S - state.a1, state.d1*S - state.a2)) + S-1) / S;
    state.d1 -= sab_rounds;
    state.d2 -= sab_rounds;
    // player 1 can't attack and player 2 can't sabotage
    if(state.a1 <= state.d2*S && state.d1 == 0 && state.a2 < S){
        ll beta2 = S - state.a2;
        ll rounds = (state.d2*S - state.a1 + beta2-1) / beta2;
        state.d2 -= rounds;
        state.a1 -= rounds * state.a2;
        if(state.d2 < 0 || state.a1 <= 0) return false;
    }
    // player 1 can't attack
    if(state.a1 <= state.d2*S) return !wins(sab(state));
    // helpful values
    ll alpha1 = state.a1 - S*state.d2;
    ll alpha2 = state.a2 - S*state.d1;
    ll beta2 = min(S, S - alpha2);
    // player 1 must attack
    if(alpha1 >= S && alpha2 <= S) return true;
    if(alpha2 >= S){
        // calls++;
        return !wins(att(state));
    }
    if(state.d2 == 0) return !wins(att(state));
    // Can player 1 win by repeated sabotage?
    if(state.d2 >= S) return true; // prevent overflow!
    if(alpha1 + state.d2 * beta2 >= S) return true;
    // Prevent opponent win by repeated sabotage:
    if(state.d1 > 0){
        ll minAlpha1 = (S * (state.d1 - 1) + alpha2) / (state.d1 + 1);
        ll sabs_todo = min(state.d2, (max(0ll, minAlpha1 - alpha1) + beta2-1) / beta2);
        state.d2 -= sabs_todo;
        state.a1 -= sabs_todo * alpha2;
    }
    if(state.d2 == 0) return !wins(att(state));
    // Can player 1 win by using half of his sabotages?
    if(half_sab_win(state)) return true;
    // Now we need dp.
    ll minA1 = calc(state.d1, state.d2, state.a2);
    return state.a1 >= minA1;
}
// It can be proven that we need O(1) iterations when min(d1, d2) > 1
bool winsSafe(State state){
    if(state.a1 <= state.d2*S) return !wins(sab(state));
    if(state.d2 == 0) return !winsSafe(att(state));
    return !wins(sab(state)) || !winsSafe(att(state));
}
ll calc(ll d1, ll d2, ll a2){
    ll beta2 = S*(d1+1) - a2;
    if(dp[d2][d1][beta2] != -1) return dp[d2][d1][beta2] + S*d2;
    ll lo = d2*S+1, hi = (d2+1)*S;
    for(ll a1 = (lo+hi)/2; lo<hi; a1 = (lo+hi)/2){
        State state = {a1, d1, a2, d2};
        bool good = !wins(sab(state)) || !winsSafe(att(state));
        if(good) hi = a1;
        else lo = a1+1;
    }
    dp[d2][d1][beta2] = lo - S*d2;
    calls++;
    return lo;
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int Q;
    cin >> S >> Q;
    ll totalSize = 0;
    dp.resize(1);
    for(ll d2 = 1; d2*d2 <= 8*S; d2++){
        vector<vector<int>> inner(min(S, 1 + 8*S/(max(1ll, d2*d2))));
        for(ll d1 = 0; d1 < S && d1*d2*d2 <= 8*S; d1++){
            ll mySize = min(S, 1 + 8*S/max(1ll, d1)/(d2*d2));
            totalSize += mySize;
            inner[d1].assign(mySize, -1);
        }
        dp.push_back(inner);
    }
    for(ll d2 = 1; d2*d2 <= 8*S; d2++){
        for(ll d1 = 0; d1 < S && d1*d2*d2 <= 8*S; d1++){
            ll mySize = min(S, 1 + 8*S/max(1ll, d1)/max(1ll, d2*d2));
            for(ll b2 = 1; b2 < mySize; b2++){
                ll minAlpha1 = (S * d1 - b2) / (d1 + 1);
                State state{S*d2+minAlpha1, d1, S*(d1+1)-b2, d2};
                if(minAlpha1 > 0 && minAlpha1 + d2*b2 < S && !half_sab_win(state)){
                    calc(d1, d2, S*(d1+1) - b2);
                };
            }
        }
    }
    for(int q = 0; q < Q; q++){
        ll a1, d1, a2, d2;
        cin >> a1 >> d1 >> a2 >> d2;
        cout << (wins({a1, d1, a2, d2}) ? "YES" : "NO") << "\n";
    }
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |