Submission #1105458

#TimeUsernameProblemLanguageResultExecution timeMemory
1105458jerzykSphinx's Riddle (IOI24_sphinx)C++17
100 / 100
642 ms1728 KiB
#include <bits/stdc++.h>
#include "sphinx.h"

using namespace std;
#define pb push_back
#define st first
#define nd second
typedef long long ll;
typedef long double ld;
const ll I = 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL;
const int II = 2 * 1000 * 1000 * 1000;
const ll M = 1000LL * 1000LL * 1000LL + 7LL;
const int N = 250 + 7;
int fau[N], ansclr[N];
vector<int> ed[N], ed2[N];
bool vis[N];
vector<int> dfst, vset[2];

int Find(int v)
{
    if(fau[v] == v) return v;
    return (fau[v] = Find(fau[v]));
}

void Union(int a, int b)
{
    //cout << "Union " << a << " " << b << "\n";
    a = Find(a); b = Find(b);
    fau[max(a, b)] = min(a, b);
}

void DFSN2(int v)
{
    vis[v] = true;
    for(int i = 0; i < (int)ed[v].size(); ++i)
    {
        if(Find(v) != Find(ed[v][i]))
            ed2[Find(v)].pb(Find(ed[v][i]));
        if(vis[ed[v][i]])
            continue;
        DFSN2(ed[v][i]);
    }
}

void DFSclr(int v, int c)
{
    vis[v] = true;
    vset[c].pb(v);
    for(int i = 0; i < (int)ed2[v].size(); ++i)
        if(!vis[ed2[v][i]])
            DFSclr(ed2[v][i], c ^ 1);
}

void DoNew(int n)
{
    DFSN2(0);
    for(int i = 0; i < n; ++i) vis[i] = false;
    for(int i = 0; i < n; ++i)
    {
        vector<int> nw;
        sort(ed2[i].begin(), ed2[i].end());
        for(int j = 0; j < (int)ed2[i].size(); ++j)
            if(j == 0 || ed2[i][j] != ed2[i][j - 1])
                nw.pb(ed2[i][j]);
        ed2[i] = nw;
    }
    DFSclr(0, 0);
    for(int i = 0; i < n; ++i) vis[i] = false;
}

void DFS(int v)
{
    vis[v] = true;
    for(int i = 0; i < (int)ed[v].size(); ++i)
        if((!vis[ed[v][i]]) && dfst[ed[v][i]] == dfst[v])
            DFS(ed[v][i]);
}

int Sus(vector<int> que)
{
    int ans = 0, n = que.size();
    dfst.clear();
    for(int i = 0; i < n; ++i)
        if(que[i] != -1)
            dfst.pb(que[i]);
        else
            dfst.pb(-Find(i) - 1);
    for(int i = 0; i < n; ++i)
        if(!vis[i])
        {
            ++ans;
            DFS(i);
        }
    for(int i = 0; i < n; ++i) vis[i] = false;
    return ans;
}

void D1(int n)
{
    vector<int> bas(n, -1), que;
    for(int i = 0; i < n; ++i)
    {
        que = bas;
        que[1] = i;
        if(perform_experiment(que) == 1)
            ansclr[0] = i;
    }
}

void FindClr(int n)
{
    vector<int> bas(n, -1), cur, que;
    cur = vset[1];
    //cerr << "beg " << vset[1].size() << "\n";
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < (int)vset[0].size(); ++j)
            bas[vset[0][j]] = i;
        for(int j = 0; j < (int)vset[1].size(); ++j)
            bas[vset[1][j]] = -1;
        for(int j = 0; j < n; ++j) bas[j] = bas[Find(j)];
        que = bas;
        //for(int j = 0; j < n; ++j)
            //cout << que[j] << " ";
        //cout << "\n";
        int ant = Sus(que);
        int akt = perform_experiment(que);
        int il = ant - akt;
        //cerr << "Clr: " << i << " " << ant << " " << akt << "\n";
        while(il > 0)
        {
            int p = 0, s, k = (int)cur.size() - 1;
            while(p < k)
            {
                s = (p + k) / 2;
                que = bas;
                for(int j = s + 1; j < (int)cur.size(); ++j)
                    que[cur[j]] = n;
                for(int j = 0; j < n; ++j) que[j] = que[Find(j)];
                int abc = Sus(que);
                if(perform_experiment(que) < abc)
                    k = s;
                else
                    p = s + 1;
            }
            //if(cur.size() == 0) return;
            //cerr << "F: " << cur[p] << " " << il << "\n";
            que = bas;
            //for(int j = 0; j < n; ++j)
                //cerr << que[j] << " ";
            //cout << "\n";
            int xd = Sus(que);
            que[cur[p]] = i;
            for(int j = 0; j < n; ++j) que[j] = que[Find(j)];
            /*for(int j = 0; j < n; ++j)
                cerr << que[j] << " ";
            cerr << "\n";*/
            int xd2 = Sus(que);
            //cerr << xd << " " << xd2 << "\n";
            il -= (xd - xd2);
            ansclr[cur[p]] = i;
            bas[cur[p]] = i;
            for(int j = 0; j < n; ++j) bas[j] = bas[Find(j)];
            vector<int> nw;
            for(int j = 0; j < (int)cur.size(); ++j)
                if(j != p)
                nw.pb(cur[j]);
            cur = nw;
        }
    }
}

void FN(int v, int il, int n)
{
    vector<int> cur, bas(n, n), que, ss;
    
    for(int i = 0; i < (int)ed[v].size(); ++i)
        if(!vis[Find(ed[v][i])] && ed[v][i] < v)
        {
            cur.pb(Find(ed[v][i]));
            vis[cur.back()] = true;
        }
    for(int i = 0; i < (int)cur.size(); ++i)
        vis[cur[i]] = false;
    while(il--)
    {
        int p = 0, s, k = cur.size() - 1;
        while(p < k)
        {
            s = (p + k) / 2;
            que = bas;
            for(int i = 0; i <= s; ++i)
                que[cur[i]] = -1;
            que[v] = -1;
            for(int i = 0; i < n; ++i) que[i] = que[Find(i)];
            int ans = perform_experiment(que);
            int ant = Sus(que);
            if(ans < ant)
                k = s;
            else
                p = s + 1;
        }
        ss.pb(cur[p]);
        vector<int> nw;
        for(int i = p + 1; i < (int)cur.size(); ++i) nw.pb(cur[i]);
        cur = nw;
    }
    for(int i = 0; i < (int)ss.size(); ++i)
        Union(v, ss[i]);
}

vector<int> find_colours(int _N, vector<int> _X, vector<int> _Y)
{
    int n = _N;
    vector<int> answer;
    for(int i = 0; i < (int)_X.size(); ++i)
    {
        ed[_X[i]].pb(_Y[i]);
        ed[_Y[i]].pb(_X[i]);
    }
    vector<int> cq(n, n);
    for(int i = 0; i < n; ++i)
        fau[i] = i;

    cq[0] = -1;
    for(int i = 1; i < n; ++i)
    {
        cq[i] = -1;
        int akt = perform_experiment(cq);
        int ant = Sus(cq);
        //cerr << "F:\n";
        //for(int j = 0; j < n; ++j)
            //cerr << Find(j) << " ";
        //cout << "\n";
        //cerr << "Sp: " << i << " " << akt << " " << ant << "\n";
        FN(i, ant - akt, n);
    }
    DoNew(n);
    if((int)vset[1].size() == 0)
        D1(n);
    else
    {
        FindClr(n);
        swap(vset[1], vset[0]);
        FindClr(n);
    }

    for(int i = 0; i < n; ++i)
        answer.pb(ansclr[Find(i)]);
    return answer;
}
#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...