This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
//#include "grader.cpp"
#include <tuple>
#include <random>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
const int MAXN = 1e5 + 5;
mt19937 rnd(22);
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, int *k)
{
//cout << a[x].l << " " << a[x].r << " -> " << a[x].maxDepth << " || " << getMax(a[x].l, a[x].r-1, k) << '\n';
if(getMax(a[x].l, a[x].r-1, k)<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, k));
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);
pair <int, int> raw = yoanko.findBest(N+C-1, R, K);
//cout << raw.first << '\n';
return yoanko.getAns(yoanko.findNode(N+C, -raw.second, raw.first), raw.first);
}
Compilation message (stderr)
tournament.cpp: In member function 'int Tree::findNode(int, int, int)':
tournament.cpp:194:5: warning: control reaches end of non-void function [-Wreturn-type]
194 | }
| ^
tournament.cpp: In member function 'int Tree::getAns(int, int)':
tournament.cpp:186:5: warning: control reaches end of non-void function [-Wreturn-type]
186 | }
| ^
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |