#include <bits/stdc++.h>
#include "plants.h"
using namespace std;
template <size_t L>
struct segtree
{
struct node
{
int64_t min_value, lazy;
size_t min_index;
node() { min_value = INT64_MAX; }
};
node t[L << 1];
node combine(node const &a, node const &b)
{
node z;
z.lazy = 0;
z.min_value = min(a.min_value, b.min_value);
z.min_index = a.min_value == z.min_value ? a.min_index : b.min_index;
return z;
}
void build()
{
for (size_t i = L; i < L << 1; ++i)
t[i].min_index = i - L;
for (size_t i = L - 1; i; --i)
t[i] = combine(t[i << 1], t[i << 1 | 1]);
}
void propagate(size_t k)
{
t[k << 1].lazy += t[k].lazy;
t[k << 1].min_value += t[k].lazy;
t[k << 1 | 1].lazy += t[k].lazy;
t[k << 1 | 1].min_value += t[k].lazy;
t[k].lazy = 0;
}
void update_point(size_t i, int64_t x, size_t k = 1, size_t a = 0, size_t b = L - 1)
{
if (a == b)
{
t[k].min_value = x;
return;
}
propagate(k);
if (i <= (a + b) / 2)
update_point(i, x, k << 1, a, (a + b) / 2);
else
update_point(i, x, k << 1 | 1, (a + b) / 2 + 1, b);
t[k] = combine(t[k << 1], t[k << 1 | 1]);
}
void decrement(size_t i, size_t j, size_t k = 1, size_t a = 0, size_t b = L - 1)
{
if (b < i || a > j)
return;
if (i <= a && b <= j)
{
t[k].lazy--;
t[k].min_value--;
}
else
{
propagate(k);
decrement(i, j, k << 1, a, (a + b) / 2);
decrement(i, j, k << 1 | 1, (a + b) / 2 + 1, b);
t[k] = combine(t[k << 1], t[k << 1 | 1]);
}
}
void cyclic_decrement(size_t i, size_t j, size_t n)
{
if (i <= j)
decrement(i, j);
else
decrement(i, n - 1), decrement(0, j);
}
node argmin(size_t i, size_t j, size_t k = 1, size_t a = 0, size_t b = L - 1)
{
if (b < i || a > j)
return node();
if (i <= a && b <= j)
return t[k];
propagate(k);
return combine(argmin(i, j, k << 1, a, (a + b) / 2),
argmin(i, j, k << 1 | 1, (a + b) / 2 + 1, b));
}
pair<size_t, int64_t> cyclic_argmin(size_t i, size_t j, size_t n)
{
node ans;
if (i <= j)
ans = argmin(i, j);
else
ans = combine(argmin(i, n - 1), argmin(0, j));
return {ans.min_index, ans.min_value};
}
};
constexpr size_t N = 200000, LGN = 18, L = 1 << LGN;
size_t n, k, h[N], curr_rank, left_jmp[LGN][N][2], right_jmp[LGN][N][2];
segtree<L> tree;
size_t cyclic_distance(size_t i, size_t j, bool goes_left)
{
if (goes_left)
{
if (i >= j)
return i - j;
return n - j + i;
}
else
{
if (i <= j)
return j - i;
return n - i + j;
}
}
void rank_plant(size_t i)
{
auto [lowest, val] = tree.cyclic_argmin((i - k + 1 + n) % n, (i - 1 + n) % n, n);
while (!val)
{
rank_plant(lowest);
tie(lowest, val) = tree.cyclic_argmin((i - k + 1 + n) % n, (i - 1 + n) % n, n);
}
h[i] = curr_rank--;
tree.update_point(i, INT64_MAX);
tree.cyclic_decrement((i - k + 1 + n) % n, (i - 1 + n) % n, n);
}
void init(int k_, std::vector<int> r)
{
k = k_;
n = r.size();
for (size_t i = 0; i < n; ++i)
tree.t[L + i].min_value = r[i];
tree.build();
curr_rank = n;
while (curr_rank)
rank_plant(tree.argmin(0, n - 1).min_index);
// reuse segment tree for storing heights
vector<size_t> plants(n);
iota(plants.begin(), plants.end(), 0);
sort(plants.begin(), plants.end(), [&](size_t const &a, size_t const &b)
{ return h[a] > h[b]; });
for (size_t i = 0; i < L; ++i)
tree.t[i].lazy = 0;
for (size_t const &i : plants)
{
auto [min_index, min_value] = tree.cyclic_argmin((i - k + 1 + n) % n, (i - 1 + n) % n, n);
if (min_value != INT64_MAX)
{
left_jmp[0][i][0] = min_index;
left_jmp[0][i][1] = cyclic_distance(i, min_index, 1);
}
else
{
left_jmp[0][i][0] = n;
left_jmp[0][i][1] = UINT32_MAX;
}
tie(min_index, min_value) = tree.cyclic_argmin((i + 1) % n, (i + k - 1) % n, n);
if (min_value != INT64_MAX)
{
right_jmp[0][i][0] = min_index;
right_jmp[0][i][1] = cyclic_distance(i, min_index, 1);
}
else
{
right_jmp[0][i][0] = n;
right_jmp[0][i][1] = UINT32_MAX;
}
tree.update_point(i, h[i]);
}
left_jmp[0][n][0] = n;
right_jmp[0][n][0] = n;
for (size_t j = 1; j < LGN; ++j)
for (size_t i = 0; i < n; ++i)
{
left_jmp[j][i][0] = left_jmp[j - 1][left_jmp[j - 1][i][0]][0];
left_jmp[j][i][1] = left_jmp[j - 1][i][1] + left_jmp[j - 1][left_jmp[j - 1][i][0]][1];
right_jmp[j][i][0] = right_jmp[j - 1][right_jmp[j - 1][i][0]][0];
right_jmp[j][i][1] = right_jmp[j - 1][i][1] + right_jmp[j - 1][right_jmp[j - 1][i][0]][1];
}
}
bool is_less(size_t x, size_t y)
{
size_t u = x, d = cyclic_distance(x, y, 1);
for (size_t i = LGN - 1; i < LGN; --i)
if (left_jmp[i][u][1] <= d)
d -= left_jmp[i][u][1], u = left_jmp[i][u][0];
if (d >= k)
u = left_jmp[0][u][0];
if (u != n && h[u] < h[y])
return 1;
u = x, d = cyclic_distance(x, y, 0);
for (size_t i = LGN - 1; i < LGN; --i)
if (right_jmp[i][u][1] <= d)
d -= right_jmp[i][u][1], u = right_jmp[i][u][0];
if (d >= k)
u = right_jmp[0][u][0];
if (u != n && h[u] < h[y])
return 1;
return 0;
}
int compare_plants(int x, int y)
{
if (abs(x - y) < k)
return h[x] > h[y] ? 1 : -1;
return is_less(x, y) ? -1 : (is_less(y, x) ? 1 : 0);
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
7 ms |
12884 KB |
Output is correct |
2 |
Correct |
6 ms |
12884 KB |
Output is correct |
3 |
Correct |
5 ms |
12884 KB |
Output is correct |
4 |
Incorrect |
5 ms |
12868 KB |
Output isn't correct |
5 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
12884 KB |
Output is correct |
2 |
Correct |
6 ms |
12884 KB |
Output is correct |
3 |
Correct |
6 ms |
12884 KB |
Output is correct |
4 |
Incorrect |
6 ms |
12884 KB |
Output isn't correct |
5 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
12884 KB |
Output is correct |
2 |
Correct |
6 ms |
12884 KB |
Output is correct |
3 |
Correct |
6 ms |
12884 KB |
Output is correct |
4 |
Incorrect |
6 ms |
12884 KB |
Output isn't correct |
5 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
12844 KB |
Output is correct |
2 |
Correct |
6 ms |
12852 KB |
Output is correct |
3 |
Incorrect |
98 ms |
17144 KB |
Output isn't correct |
4 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
7 ms |
12856 KB |
Output is correct |
2 |
Correct |
6 ms |
12884 KB |
Output is correct |
3 |
Incorrect |
6 ms |
12840 KB |
Output isn't correct |
4 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
12884 KB |
Output is correct |
2 |
Correct |
6 ms |
12884 KB |
Output is correct |
3 |
Incorrect |
6 ms |
12884 KB |
Output isn't correct |
4 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
7 ms |
12884 KB |
Output is correct |
2 |
Correct |
6 ms |
12884 KB |
Output is correct |
3 |
Correct |
5 ms |
12884 KB |
Output is correct |
4 |
Incorrect |
5 ms |
12868 KB |
Output isn't correct |
5 |
Halted |
0 ms |
0 KB |
- |