제출 #249730

#제출 시각아이디문제언어결과실행 시간메모리
249730stoyan_malininMechanical Doll (IOI18_doll)C++14
2 / 100
1084 ms52360 KiB
#include "doll.h"
//#include "grader.cpp"

#include <iostream>
#include <set>

using namespace std;

const int MAXN = 5e5 + 5;

int usedSwitches = 0;

struct Switch
{
    static int switchCnt;

    int num;
    int state;

    int out[2];

    Switch()
    {
        this->num = switchCnt;
        switchCnt++;

        this->state = 0;
        this->out[0] = this->out[1] = MAXN;
    }
};
int Switch::switchCnt = 0;

Switch s[MAXN];
bool removed[MAXN];

struct RouterOutput
{
    int switchNum, outNum;

    RouterOutput(){}
    RouterOutput(int switchNum, int outNum)
    {
        this->outNum = outNum;
        this->switchNum = switchNum;
    }

    void assignDirection(int nxt)
    {
        s[switchNum].out[outNum] = nxt;
    }
};

struct Router
{
    int root, sz, useless;
    vector <RouterOutput> outs;

    int removedCnt = 0;

    Router(){}
    Router(int sz, int useless)
    {
        usedSwitches++;

        this->root = usedSwitches;

        this->sz = sz;
        this->useless = useless;
        build(root, 0, sz-1);

        optimize(root);
        initOuts();
    }

    void optimize(int sInd)
    {
        //cout << sInd << " -> " << s[sInd].out[0] << '\n';
        if(s[sInd].out[0]==MAXN)
        {
            if(useless>=2)
            {
                useless -= 2;
                removed[sInd] = 1;

                //cout << "remove*: " << sInd << '\n';

                removedCnt++;
            }
            return;
        }

        optimize(-s[sInd].out[0]);
        optimize(-s[sInd].out[1]);

        if(removed[ -s[sInd].out[0] ]==true && removed[ -s[sInd].out[1] ]==true)
        {
            //cout << "remove: " << sInd << '\n';

            removed[sInd] = 1;
            removedCnt++;
        }
        else if(removed[ -s[sInd].out[0] ]==true)
        {
            s[sInd].out[0] = -root;
        }
        else if(removed[ -s[sInd].out[1] ]==true)
        {
            s[sInd].out[1] = -root;
        }
    }

    void build(int sInd, int l, int r)
    {
        //cout << sInd << " || " << l << " " << r << '\n';

        if(l+1==r) return;
        if(l+2==r)
        {
            usedSwitches++;
            s[sInd].out[0] = -usedSwitches;

            return;
        }

        usedSwitches++;
        s[sInd].out[0] = -usedSwitches;

        usedSwitches++;
        s[sInd].out[1] = -usedSwitches;

        build(-s[sInd].out[0], l, (l+r)/2);
        build(-s[sInd].out[1], (l+r)/2+1, r);
    }

    void initOuts()
    {
        for(int i = 0;i<sz;i++)
        {
            int sInd = root;
            while(true)
            {
                if(s[sInd].out[ s[sInd].state ]==MAXN)
                {
                    outs.push_back(RouterOutput(sInd, s[sInd].state));
                    s[sInd].state ^= 1;

                    break;
                }

                s[sInd].state ^= 1;
                sInd = -s[sInd].out[ s[sInd].state^1 ];
            }
        }

        //if(outs.size()!=sz) answer({}, {}, {});
        //for(RouterOutput x: outs) cout << x.switchNum << " " << x.outNum << '\n';
    }
};

Router r[MAXN];
vector <int> nxt[MAXN];

void relabel(vector <int> &c, vector <int> &x, vector <int> &y)
{
    set <int> s;
    for(int a: c)
    {
        if(a<0) s.insert(-a);
    }
    for(int a: x)
    {
        if(a<0) s.insert(-a);
    }
    for(int a: y)
    {
        if(a<0) s.insert(-a);
    }

    int ind = 0;
    for(int a: s)
    {
        ind++;
        //cout << a << " vs " << ind << '\n';

        for(int &b: c)
        {
            if(b==-a) b = -ind;
        }
        for(int &b: x)
        {
            if(b==-a) b = -ind;
        }
        for(int &b: y)
        {
            if(b==-a) b = -ind;
        }

        swap(x[a-1], x[ind-1]);
        swap(y[a-1], y[ind-1]);
    }

    while(x.size()!=ind) x.pop_back(), y.pop_back();
}

void create_circuit(int M, vector <int> A)
{
    vector <int> C(M+1);

    A.push_back(0);
    for(int i = 0;i<A.size()-1;i++) nxt[ A[i] ].push_back(A[i+1]);

    C[0] = A[0];
    for(int i = 1;i<=M;i++)
    {
        if(nxt[i].size()>1)
        {
            int sz = 1;
            while(sz<nxt[i].size()) sz *= 2;

            r[i] = Router(sz, sz-nxt[i].size());
            C[i] = -r[i].root;
        }
        else
        {
            if(nxt[i].size()==1) C[i] = nxt[i][0];
            else C[i] = 0;
        }
    }

    for(int x = 1;x<=M;x++)
    {
        if(nxt[x].size()<=1) continue;

        int useLess = r[x].useless;
        for(int i = 0;i<useLess;i++) r[x].outs[i].assignDirection(-r[x].root);

        for(int i = 0;i<nxt[x].size();i++)
        {
            r[x].outs[useLess+i].assignDirection(nxt[x][i]);
        }
    }

    //cout << '\n';

    //for(int i = 0;i<=M;i++) cout << C[i] << '\n';

    vector <int> X(usedSwitches), Y(usedSwitches);
    for(int i = 1;i<=usedSwitches;i++)
    {
        X[i-1] = s[i].out[0];
        Y[i-1] = s[i].out[1];

        //cout << X[i-1] << " " << Y[i-1] << '\n';
    }

    if(usedSwitches>=2*(A.size()-1)) cout << 1/0 << '\n';

    relabel(C, X, Y);
    answer(C, X, Y);
}
/*
4 4
1 2 1 3

4 7
1 3 4 2 1 2 2

5 5
1 1 1 1 1

5 11
1 2 5 2 3 4 1 2 5 5 4

5 4
1 1 1 1
*/

컴파일 시 표준 에러 (stderr) 메시지

doll.cpp: In function 'void relabel(std::vector<int>&, std::vector<int>&, std::vector<int>&)':
doll.cpp:202:19: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  202 |     while(x.size()!=ind) x.pop_back(), y.pop_back();
      |           ~~~~~~~~^~~~~
doll.cpp: In function 'void create_circuit(int, std::vector<int>)':
doll.cpp:210:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  210 |     for(int i = 0;i<A.size()-1;i++) nxt[ A[i] ].push_back(A[i+1]);
      |                   ~^~~~~~~~~~~
doll.cpp:218:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  218 |             while(sz<nxt[i].size()) sz *= 2;
      |                   ~~^~~~~~~~~~~~~~
doll.cpp:237:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  237 |         for(int i = 0;i<nxt[x].size();i++)
      |                       ~^~~~~~~~~~~~~~
doll.cpp:256:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  256 |     if(usedSwitches>=2*(A.size()-1)) cout << 1/0 << '\n';
      |        ~~~~~~~~~~~~^~~~~~~~~~~~~~~~
doll.cpp:256:47: warning: division by zero [-Wdiv-by-zero]
  256 |     if(usedSwitches>=2*(A.size()-1)) cout << 1/0 << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...