Submission #824988

#TimeUsernameProblemLanguageResultExecution timeMemory
824988phoenixCrossing (JOI21_crossing)C++17
100 / 100
273 ms40400 KiB
#include<bits/stdc++.h>

using namespace std;
using ll = long long;

namespace hashing {

    struct H {
        int len;
        ll h1;
        unsigned long long h2;
        H() : len(0), h1(0), h2(0) {} 
        H(int c) : len(1), h1(c), h2(c) {}

    };
    map<char, int> tran = {
        {'J', 0},
        {'O', 1},
        {'I', 2}
    };

    const int MOD = 1e9 + 7, MAX_LEN = 2e5 + 10;
    ll p1[MAX_LEN];
    unsigned long long p2[MAX_LEN];
    mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
    H spam_str[MAX_LEN][3];
    H operator + (const H a, const H b) {
        H res;
        res.len = a.len + b.len;
        res.h1 = (a.h1 * p1[b.len] + b.h1) % MOD;
        res.h2 = (a.h2 * p2[b.len] + b.h2);
        return res;
    }
    bool operator == (const H a, const H b) {
        bool res = 1;
        res &= (a.len == b.len);
        res &= (a.h1 == b.h1);
        res &= (a.h2 == b.h2);
        return res;
    }

    void H_precalc() {
        p1[0] = p2[0] = 1;
        int p = rnd() % 500 * 2 + 10;
        int q = rnd() % 500 * 2 + 10;
        for(int i = 1; i < MAX_LEN; i++) 
            p1[i] = p1[i - 1] * p % MOD,
            p2[i] = p2[i - 1] * q;
        for(int i = 1; i < MAX_LEN; i++) {
            spam_str[i][0] = spam_str[i - 1][0] + H(0);
            spam_str[i][1] = spam_str[i - 1][1] + H(1);
            spam_str[i][2] = spam_str[i - 1][2] + H(2);
        }
    }

    const int M = (1 << 18);
    H tr[2 * M];
    vector<int> upd(2 * M, -1);
    
    void setpush(int v, int l, int r, int x) {
        tr[v] = spam_str[r - l + 1][x];
        upd[v] = x;
    }
    void push(int v, int l, int r) {
        if(l == r || upd[v] == -1) return;
        int mid = (l + r) / 2;
        setpush(2 * v, l, mid, upd[v]);
        setpush(2 * v + 1, mid + 1, r, upd[v]);
        upd[v] = -1;
    }
    void build(string &t, int l = 0, int r = M - 1, int v = 1) {
        if(l == r) {
            if(l < (int)t.size()) tr[v] = H(tran[t[l]]);
            return;
        }
        int mid = (l + r) / 2;
        build(t, l, mid, 2 * v);
        build(t, mid + 1, r, 2 * v + 1);
        tr[v] = tr[2 * v] + tr[2 * v + 1];
    }
    void update(char c, int ql, int qr, int l = 0, int r = M - 1, int v = 1) {
        if(r < ql || l > qr) return;
        if(ql <= l && r <= qr) {
            setpush(v, l, r, tran[c]);
            return;
        }
        push(v, l, r);
        int mid = (l + r) / 2;
        update(c, ql, qr, l, mid, 2 * v);
        update(c, ql, qr, mid + 1, r, 2 * v + 1);
        tr[v] = tr[2 * v] + tr[2 * v + 1];
    }
};
using namespace hashing;


int n;
string T = "JOI";

string get(string a, string b) {
    string res;
    for(int i = 0; i < n; i++)
        if(a[i] == b[i]) res += a[i];
        else {
            int k = 0;
            while(T[k] == a[i] || T[k] == b[i]) k++;
            res += T[k];
        }
    return res;
}
vector<string> st;
vector<H> h;
bool check() {
    for(H cur : h)
        if(cur == tr[1]) return 1;
    return 0;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    hashing::H_precalc();

    cin >> n;
    string s[3];
    cin >> s[0] >> s[1] >> s[2];
    st.push_back(s[0]);
    st.push_back(s[1]);
    st.push_back(s[2]);
    st.push_back(get(s[0], s[1]));
    st.push_back(get(s[0], s[2]));
    st.push_back(get(s[1], s[2]));
    st.push_back(get(s[0], get(s[1], s[2])));
    st.push_back(get(s[0], get(s[2], s[1])));
    st.push_back(get(s[1], get(s[0], s[2])));
    st.push_back(get(s[1], get(s[2], s[0])));
    st.push_back(get(s[2], get(s[0], s[1])));
    st.push_back(get(s[2], get(s[1], s[0])));
    for(string c : st) {
        H res;
        for(int i = 0; i < n; i++) 
            res = res + H(tran[c[i]]);
        h.push_back(res);
    }

    int q;
    cin >> q;
    string t;
    cin >> t;
    build(t);

    cout << (check() ? "Yes\n" : "No\n");
    while(q--) {
        int l, r; char x;
        cin >> l >> r >> x;
        l--; r--;
        update(x, l, r);
        cout << (check() ? "Yes\n" : "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...