Submission #1239766

#TimeUsernameProblemLanguageResultExecution timeMemory
1239766farukCrossing (JOI21_crossing)C++20
100 / 100
888 ms84484 KiB
#include <bits/stdc++.h>
#define all(a) a.begin(), a.end()

using namespace std;

typedef __uint128_t ll;
typedef pair<ll, ll> pii;

const ll P1 = 23;
const ll P2 = 31;
const ll mod2 = 1e18 + 7;
const ll mod1 = 1e17 + 9;
const ll maxn = 3e5;

ll merge(ll l, ll r, ll v1, ll v2, ll mod, vector<ll> &powp) {
    return ((powp[r - l + 1] * v2) % mod + v1) % mod;
}

map<char, ll> trans = {{'J', 43}, {'O', 39}, {'I', 53}};
struct seggy { 
    ll mod;
    ll n, P;
    vector<ll> seg, lazy, powp, csum;
    seggy() {}
    seggy(ll n, ll mod, ll P) : P(P), mod(mod), n(n), seg(vector<ll>(4 * n)), lazy(vector<ll>(4 * n)) {
        powp = csum = vector<ll>(maxn, 1);
        for (ll i = 1; i < maxn; i++)
            powp[i] = powp[i - 1] * P % mod;
        csum[0] = 0;
        for (ll i = 2; i < maxn; i++)
            csum[i] = (csum[i - 1] + powp[i - 1]) % mod;
    }

    void push(ll l, ll r, ll idx) {
        if (lazy[idx] == 0)
            return;
        seg[idx] = csum[r - l + 1] * lazy[idx] % mod;
        if (l != r)
            lazy[idx * 2] = lazy[idx * 2 + 1] = lazy[idx];
        lazy[idx] = 0;
    }

    void upd(ll l, ll r, ll L, ll R, ll idx, ll val) {
        push(l, r, idx);
        if (l >= L and r <= R) {
            lazy[idx] = val;
            push(l, r, idx);
            return;
        }
        if (l > R || r < L)
            return;
        ll mid = (l + r) / 2;
        upd(l, mid, L, R, idx * 2, val);
        upd(mid + 1, r, L, R, idx * 2 + 1, val);
        seg[idx] = merge(l, mid, seg[idx * 2], seg[idx * 2 + 1], mod, powp);
    }

    void upd(ll l, ll r, ll val) {
        upd(0, n - 1, l, r, 1, val);
    }

    ll query() {
        push(0, n  - 1, 1);
        return seg[1];
    }
};

ll get_hsh(string I, seggy& seg) {
     ll hsh = 0;
    for (ll t = 0; t < I.size(); t++)
        hsh = (hsh + (trans[I[t]] * seg.powp[t] % seg.mod)) % seg.mod;
    return hsh;
}


string cross(string a, string b) {
    string c = "";
    for (int i = 0; i < a.size(); i++) {
        if (a[i] == b[i])
            c += a[i];
        else
            c += ('J' + 'O' + 'I' - a[i] - b[i]);
    }
    return c;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n;
    cin >> n;
    vector<string> s(3);
    for (ll i = 0; i < 3; i++)
        cin >> s[i];

    vector<bool> forced(n, true);
    for (ll i = 0; i < n; i++)
    {
        if (s[0][i] != s[1][i] || s[0][i] != s[2][i] || s[1][i] != s[2][i])
            forced[i] = false;
    }

    vector<ll> cmp(n);
    vector<vector<ll>> per(4); 
    /*
    0, 1  and 2 are diff
    1, 0 and 2 are diff
    2, 0 and 1 are diff
    3 all are diff
    */
    for (ll i = 0; i < n; i++)
    {
        if (forced[i])
            continue;
        set<char> s1;
        for (ll k = 0; k < 3; k++)
            s1.insert(s[k][i]);
        if (s1.size() == 3)
            per[3].push_back(i), cmp[i] = 3;
        else {
            for (ll j = 0; j < 3; j++)
            {
                bool ok = true;
                for (ll k = 0; k < 3; k++)
                    if (j != k and s[j][i] == s[k][i])
                        ok = false;
                if (ok)
                    per[j].push_back(i), cmp[i] = j;
            }
        }
    }

    ll num_comps = 0;
    vector<vector<char>> variants(3, vector<char>(n));
    for (vector<ll> ids : per)
    {
        if (!ids.empty())
            num_comps++;
        for (ll i : ids)
        {
            variants[0][i] = s[0][i], variants[1][i] = s[1][i], variants[2][i] = s[2][i];
            for (ll j = 0; j < 3; j++)
            {
                bool can_change = false;
                for (ll k = 0; k < 3; k++)
                    if (j != k and variants[j][i] == variants[k][i])
                        can_change = true;
                if (!can_change)
                    continue;
                int me = (int)'J' + (int)'O' + (int)'I';
                for (ll k = 0; k < 3; k++)
                    if (j != k)
                        me -= variants[k][i];
                variants[j][i] = (char)me;
                break;
            }
        }
    }

    seggy seg1(n, mod1, P1), seg2(n, mod2, P2);
    set<ll> poss1, poss2;
    vector<string> strs = {s[0], s[1], s[2], cross(s[0], s[1]), cross(s[0], s[2]), cross(s[1], s[2]), cross(s[0], cross(s[1], s[2])), cross(s[1], cross(s[0], s[2])), cross(s[2], cross(s[0], s[1]))};
    for (auto s : strs) {
        poss1.insert(get_hsh(s, seg1));
        poss2.insert(get_hsh(s, seg2));
    }

    string t;
    int q;
    cin >> q;
    cin >> t;
    for (ll i = 0; i < n; i++)
    {
        seg1.upd(i, i, trans[t[i]]);
        seg2.upd(i, i, trans[t[i]]);
    }
    for (ll Q = 0; Q <= q; Q++)
    {
        if (Q > 0)
        {
            int l, r;
            cin >> l >> r;
            char c;
            cin >> c;
            seg1.upd(l - 1, r - 1, trans[c]);
            seg2.upd(l - 1, r - 1, trans[c]);
        }
        if (poss1.count(seg1.query()) and poss2.count(seg2.query()))
            cout << "Yes\n";
        else
            cout << "No\n";
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...