답안 #287203

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
287203 2020-08-31T13:34:23 Z stoyan_malinin 마상시합 토너먼트 (IOI12_tournament) C++14
100 / 100
175 ms 35448 KB
//#include "grader.cpp"

#include <tuple>
#include <random>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

const int MAXLog = 18;
const int MAXN = 2e5 + 5;

mt19937 rnd(22);

struct SparseTable
{
    int n;
    int logVal[MAXN];
    int sparse[25][MAXN];

    SparseTable(){}
    SparseTable(int n, int *a)
    {
        this->n = n;
        this->init(a);
    }

    void init(int *a)
    {
        logVal[0] = logVal[1] = 0;
        for(int i = 2;i<=n;i++) logVal[i] = logVal[i/2] + 1;

        for(int i = 0;i<n;i++) sparse[0][i] = a[i];
        for(int step = 1;step<=MAXLog;step++)
        {
            for(int i = 0;i<n;i++)
            {
                if(i+(1<<(step-1))<n)
                {
                    sparse[step][i] = max(sparse[step-1][i], sparse[step-1][i+(1<<(step-1))]);
                }
                else
                {
                    sparse[step][i] = sparse[step-1][i];
                }
            }
        }
    }

    int getMax(int l, int r)
    {
        if(l>r) return -1;

        int log2 = logVal[r-l+1];
        return max(sparse[log2][l], sparse[log2][r-(1<<log2)+1]);
    }
};

struct Treap
{
    int length;
    pair <int, int> seg;

    int treeInd;

    int priority;
    Treap *L, *R;

    Treap()
    {
        this->length = 1;
        this->priority = rnd();

        this->L = nullptr;
        this->R = nullptr;
    }
    Treap(pair <int, int> seg, int treeInd)
    {
        this->treeInd = treeInd;

        this->seg = seg;
        this->length = 1;
        this->priority = rnd();

        this->L = nullptr;
        this->R = nullptr;
    }

    void recalc()
    {
        length = 1;
        if(L!=nullptr) length += L->length;
        if(R!=nullptr) length += R->length;
    }
};

Treap *Merge(Treap *small,  Treap *big)
{
    if(small==nullptr) return big;
    if(big==nullptr) return small;

    if(small->priority > big->priority)
    {
        small->R = Merge(small->R, big);
        small->recalc();

        return small;
    }
    else
    {
        big->L = Merge(small, big->L);
        big->recalc();

        return big;
    }
}

pair <Treap*, Treap*> SplitSz(Treap *T, int sz)
{
    if(T==nullptr) return {nullptr, nullptr};
    if(sz==0) return {nullptr, T};

    int leftSz = ((T->L==nullptr)?0:T->L->length);
    if(1+leftSz<=sz)
    {
        auto splitResult = SplitSz(T->R, sz-leftSz-1);

        T->R = splitResult.first;
        T->recalc();

        return {T, splitResult.second};
    }
    else
    {
        auto splitResult = SplitSz(T->L, sz);

        T->L = splitResult.second;
        T->recalc();

        return {splitResult.first, T};
    }
}

struct Tree
{
    struct Node
    {
        int x;
        int l, r;

        int maxDepth;

        Node(){}
        Node(int x)
        {
            this->x = x;

            this->l = MAXN;
            this->r = -1;
        }
        Node(int x, int l, int r)
        {
            this->x = x;
            this->l = l;
            this->r = r;
        }
    };

    Node a[MAXN];
    vector <int> children[MAXN];

    void addNode(Node x)
    {
        a[x.x] = x;
    }

    void addChild(int parent, int child)
    {
        children[parent].push_back(child);
    }

    void dfsInit(int x)
    {
        sort(children[x].begin(), children[x].end(),
        [&](int A, int B)
        {
            if(a[A].l!=a[B].l) return a[A].l<a[B].l;
            return a[A].r<a[B].r;
        });

        a[x].maxDepth = 0;
        for(int y: children[x])
        {
            dfsInit(y);
            a[x].maxDepth = max(a[x].maxDepth, a[y].maxDepth+1);
        }

        //cout << a[x].l << " " << a[x].r << " -> " << a[x].maxDepth << '\n';
    }

    int getMax(int l, int r, int *k)
    {
        int maxVal = 0;
        for(int i = l;i<=r;i++) maxVal = max(maxVal, k[i]);

        return maxVal;
    }

    pair <int, int> findBest(int x, int r, SparseTable &sparse)
    {
        //-cout << a[x].l << " " << a[x].r << " -> " << a[x].maxDepth << " || "
        //<< sparse.getMax(a[x].l, a[x].r-1) << '\n';
        if(sparse.getMax(a[x].l, a[x].r-1)<r) return {a[x].maxDepth, -a[x].l};

        pair <int, int> ans = {-1, -1};
        for(int y: children[x])
            ans = max(ans, findBest(y, r, sparse));


        return ans;
    }

    int getAns(int x, int depth)
    {
        if(depth==0) return a[x].l;

        for(int y: children[x])
        {
            if(a[y].maxDepth==depth-1) return getAns(y, depth-1);
        }
    }

    int findNode(int all, int l, int maxDepth)
    {
        for(int i = 0;i<all;i++)
        {
            if(a[i].l==l && a[i].maxDepth==maxDepth) return i;
        }
    }
};

int n;
int k[MAXN];

Tree yoanko;

tuple <Treap*, Treap*, Treap*> splitBySegment(Treap *&T, int l, int r)
{
    auto help1 = SplitSz(T, l);
    auto help2 = SplitSz(help1.second, r-l+1);

    return make_tuple(help1.first, help2.first, help2.second);
}

Treap *createReplacement(Treap *T, int newInd, vector <int> &children)
{
    Treap *out = new Treap();

    out->treeInd = newInd;
    out->seg = {MAXN, -1};

    function <void(Treap*)> use = [&](Treap *T)
    {
        children.push_back(T->treeInd);
        out->seg.first = min(out->seg.first, T->seg.first);
        out->seg.second = max(out->seg.second, T->seg.second);

        if(T->L!=nullptr) use(T->L);
        if(T->R!=nullptr) use(T->R);
    };

    use(T);
    return out;
}

void constructTree(int c, int *s, int *e)
{
    Treap *T = nullptr;
    for(int i = 0;i<n;i++)
    {
        Treap *add = new Treap(make_pair(i, i), i);
        yoanko.addNode(Tree::Node(i, i, i));

        T = Merge(T, add);
    }

    for(int i = 0;i<c;i++)
    {
        auto help = splitBySegment(T, s[i], e[i]);

        Treap *part1 = get<0>(help);
        Treap *part2 = get<1>(help);
        Treap *part3 = get<2>(help);

        //if(part1!=nullptr) cout << " " << part1->length;
        //if(part2!=nullptr) cout << " " << part2->length;
        //if(part3!=nullptr) cout << " " << part3->length;
        //cout << '\n';

        vector <int> children;
        Treap *replacement = createReplacement(part2, n+i, children);

        yoanko.addNode(Tree::Node(n+i, replacement->seg.first, replacement->seg.second));
        for(int child: children) yoanko.addChild(n+i, child);

        //cout << replacement->seg.first << " " << replacement->seg.second << '\n';

        T = Merge(part1, Merge(replacement, part3));
    }

    //cout << " --- " << '\n';
    yoanko.dfsInit(n+c-1);
}

int GetBestPosition(int N, int C, int R, int *K, int *S, int *E)
{
    n = N;
    for(int i = 0;i<n;i++) k[i] = K[i];

    constructTree(C, S, E);

    SparseTable sparse = SparseTable(N, K);
    pair <int, int> raw = yoanko.findBest(N+C-1, R, sparse);
    //cout << raw.first << '\n';

    return yoanko.getAns(yoanko.findNode(N+C, -raw.second, raw.first), raw.first);
}

Compilation message

tournament.cpp: In member function 'int Tree::findNode(int, int, int)':
tournament.cpp:241:5: warning: control reaches end of non-void function [-Wreturn-type]
  241 |     }
      |     ^
tournament.cpp: In member function 'int Tree::getAns(int, int)':
tournament.cpp:233:5: warning: control reaches end of non-void function [-Wreturn-type]
  233 |     }
      |     ^
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 5120 KB Output is correct
2 Correct 4 ms 5120 KB Output is correct
3 Correct 6 ms 5248 KB Output is correct
4 Correct 4 ms 5248 KB Output is correct
5 Correct 4 ms 5248 KB Output is correct
6 Correct 4 ms 5248 KB Output is correct
7 Correct 4 ms 5248 KB Output is correct
8 Correct 4 ms 5280 KB Output is correct
9 Correct 4 ms 5248 KB Output is correct
10 Correct 5 ms 5248 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 5376 KB Output is correct
2 Correct 11 ms 6656 KB Output is correct
3 Correct 6 ms 6016 KB Output is correct
4 Correct 10 ms 6400 KB Output is correct
5 Correct 10 ms 6400 KB Output is correct
6 Correct 9 ms 6144 KB Output is correct
7 Correct 11 ms 6528 KB Output is correct
8 Correct 11 ms 6528 KB Output is correct
9 Correct 6 ms 5888 KB Output is correct
10 Correct 12 ms 6400 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 76 ms 15864 KB Output is correct
2 Correct 175 ms 35448 KB Output is correct
3 Correct 64 ms 21736 KB Output is correct
4 Correct 169 ms 33656 KB Output is correct
5 Correct 151 ms 33912 KB Output is correct
6 Correct 154 ms 27580 KB Output is correct
7 Correct 161 ms 34808 KB Output is correct
8 Correct 165 ms 34808 KB Output is correct
9 Correct 55 ms 21036 KB Output is correct
10 Correct 64 ms 21624 KB Output is correct