Submission #583050

#TimeUsernameProblemLanguageResultExecution timeMemory
583050MadokaMagicaFanPaint By Numbers (IOI16_paint)C++14
100 / 100
759 ms165452 KiB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using vi = vector<int>;
using pi = pair<int,int>;

#define all(v)          v.begin(),v.end()
#define sort(v)         sort(all(v))
#define endl            '\n'
#define forn(i,n)       for(int i = 0; i < n; ++i)
#define forbe(i,b,e)    for(int i = b; i < e; ++i)
#define forr(i,n)       for(int i = n-1; i >= 0; --i)
#define sz(v)           ((int)v.size())
#define pb              push_back
#define f               first
#define s               second

struct aib{
    vi f;
    int n;

    aib(int _n) {
        n = _n;
        f.assign(n,0);
    }

    void add(int x, int v) {
        for(;x <n; x  |= (x+1))
            f[x] += v;
    }

    int q(int x) {
        int r = 0;
        for(;x >= 0; x = (x&(x+1))-1)
            r += f[x];
        return r;
    }

    int query(int l, int r) {
        return q(r) - q(l-1);
    }
};

struct psum{
    vi f;
    vi _v;
    int n;

    psum(int _n) {
        n = _n;
        f.assign(n,0);
        _v.assign(n,0);
    }

    void add(int x, int v) {
        _v[x] += v;
    }

    void gen() {
        forn(i,n) {
            if (i) f[i] = f[i-1];
            f[i] += _v[i];
        }
    }

    int q(int x) {
        if (x < 0)
            return 0;
        assert(f[x] > -1);
        return f[x];
    }

    int query(int l, int r) {
        if (r < l)
            return 0;
        assert(q(r) - q(l-1) > -1);
        return q(r) - q(l-1);
    }
};

string solve_puzzle(string s, vi c) {
    int n = sz(s);
    int k = sz(c);
    string ans = s;
    vi type(n,0);
    vi pnt(k,0);

    psum tr(n);
    psum trx(n);

    psum posseg(n+5);
    psum minseg(n+5);


    forn(i,n)
        if (s[i] == '_')
            tr.add(i,1);

    forn(i,n)
        if (s[i] == 'X')
            trx.add(i,1);

    tr.gen();
    trx.gen();

    vector<int> pdp[k];
    vector<int> sdp[k];

    forn(j,k) pdp[j].assign(n,-1);
    forn(j,k) sdp[j].assign(n,-1);

    forn(j,k) {
        int lst = 1;
        if (!j) {
            forn(i,n - c[j]+1) {
                if (i+c[j]-1) pdp[j][i+c[j]-1] = pdp[j][i+c[j]-2];
                if (pdp[j][i+c[j]-1] != -1 && (!trx.query(i+c[j]-1,i+c[j]-1) && lst))
                    continue;

                lst = 0;
                if (tr.query(i,i+c[j]-1) > 0) continue;
                if (trx.query(0,i-1) > 0) continue;
                lst = 1;

                pdp[j][i+c[j]-1] = i+c[j]-1;
            }
        } else {
            forbe(i,1,n - c[j]+1) {
                if (i+c[j]-1) pdp[j][i+c[j]-1] = pdp[j][i+c[j]-2];
                if (pdp[j][i+c[j]-1] != -1 && (!trx.query(i+c[j]-1,i+c[j]-1) && lst))
                    continue;

                lst = 0;
                if (tr.query(i,i+c[j]-1) > 0) continue;
                if (pdp[j-1][i-1] == i-1 || pdp[j-1][i-1] == -1) continue;
                if (trx.query(pdp[j-1][i-1]+1,i-1)) continue;
                lst = 1;

                pdp[j][i+c[j]-1] = i+c[j]-1;
            }
        }
    }

    forr(j,k) {
        int lst = 1;
        if (j == k-1) {
            forr(i,n-c[j]+1) {
                if (i < n-1) sdp[j][i] = sdp[j][i+1];
                if (sdp[j][i] != -1 && (!trx.query(i,i) && lst))
                    continue;

                lst = 0;
                if (tr.query(i,i+c[j]-1) > 0) continue;
                if (trx.query(i+c[j],n-1) > 0) continue;
                lst = 1;
                sdp[j][i] = i;
            }
        } else {
            forr(i,n-c[j]) {
                if (i < n-1) sdp[j][i] = sdp[j][i+1];
                if (sdp[j][i] != -1 && (!trx.query(i,i) && lst))
                    continue;

                lst = 0;
                if (tr.query(i,i+c[j]-1) > 0)    continue;
                if (sdp[j+1][i+c[j]] == i+c[j] || sdp[j+1][i+c[j]] == -1) continue;
                if (trx.query(i+c[j],sdp[j+1][i+c[j]]-1)) continue;
                lst = 1;

                sdp[j][i] = i;
            }
        }
    }

#ifdef ONPC
    forn(j,k) {
        forn(i,n) {
            if (pdp[j][i] == -1)
                cout << 0;
            else
                cout << pdp[j][i];
                /* cout << 1; */
        }
        cout << endl;
    }

    forn(j,k) {
        forn(i,n) {
            if (sdp[j][i] == -1)
                cout << 0;
            else
                cout << sdp[j][i];
        }
        cout << endl;
    }
#endif

    int il, ir;
    forn(j,k) {
        forn(i,n) {
            if (i + c[j] > n) break;
            /* cout << j << ' ' << i << ' ' << il << ' ' << ir << endl; */
            if (j) {
                if (!i) continue;
                il = pdp[j-1][i-1];
                if (il == -1 || il == i-1)
                    continue;
            } else {
                il = -1;
            }

            if (j == k-1) {
                ir = n;
            } else {
                if (i + c[j] == n) continue;
                ir = sdp[j+1][i+c[j]];
                if (ir == -1 || ir == i + c[j])
                    continue;
            }
            /* cout << j << ' ' << i << endl; */

            if (tr.query(i,i+c[j]-1) > 0) continue;
            if (trx.query(il+1, i-1)) continue;
            if (trx.query(i + c[j], ir-1)) continue;

            /* cout << j << ' ' << i << endl; */

            if (j) minseg.add(pdp[j-1][i-1]+1,1);
            else   minseg.add(0,1);
            minseg.add(i,-1);

            minseg.add(i+c[j],1);
            if (j!=k-1) minseg.add(sdp[j+1][i+c[j]],-1);

            posseg.add(i,1);
            posseg.add(i+c[j],-1);
        }
    }

    /* forn(j,k) { */
    /*     minseg.add(pnt[j]+c[j],1); */
    /*     if (j < k-1) */
    /*         minseg.add(pnt[j+1],-1); */
    /*     else */
    /*         minseg.add(n,-1); */
    /* } */
    /*  */
    /* int lm; */
    /* int lp = n+1; */
    /* forr(j,k) { */
    /*     lm = lp; */
    /*     lp = pnt[j]; */
    /*     forbe(i,pnt[j], lm - c[j]) { */
    /*         if (tr.query(i,i+c[j]-1) > 0) */
    /*             continue; */
    /*         lp = i; */
    /*         posseg.add(i,1); */
    /*         posseg.add(i+c[j],-1); */
    /*     } */
    /*  */
    /*     minseg.add(pnt[j],1); */
    /*     minseg.add(lp,-1); */
    /* } */

    posseg.gen();
    minseg.gen();
    forn(i,n) {
        if (posseg.q(i) > 0) {
            if (minseg.q(i) > 0)
                ans[i] = '?';
            else
                ans[i] = 'X';
        }
        else
            ans[i] = '_';
    }
    return ans;
}

#ifdef ONPC
void solve() {
    int n, k;
    cin >> k;
    string s;
    cin >> s;
    vi c(k);
    forn(i,k)
        cin >> c[i];
    string ans = solve_puzzle(s,c);

    cout << ans << endl;
}

int main() {
    freopen("in", "r", stdin);
//    ios_base::sync_with_stdio(0);cin.tie(0);
    solve();
}
#endif
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...