Finish this hellish problem

Holy crap... Memory limit gallore, I had to make a LOT of optimizations
on this one, and it just barely worked...
This commit is contained in:
Segcolt 2024-10-24 14:45:14 -03:00
parent 337b443085
commit 48a13b9262

View File

@ -0,0 +1,261 @@
#include <bits/stdc++.h>
using namespace std;
#define V vector
#define rmin(a, b) a = min(a, b)
#define rmax(a, b) a = max(a, b)
#define rep(i, lim) for (size_t i = 0; i < (lim); i++)
#define nrep(i, s, lim) for (size_t i = s; i < (lim); i++)
#define repv(i, v) for (auto &i : (v))
#define fillv(v) for (auto &itr_ : (v)) { cin >> itr_; }
#define sortv(v) sort(v.begin(), v.end())
#define all(v) (v).begin(), (v).end()
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vvvvi = vector<vvvi>;
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
using vvvvl = vector<vvvl>;
template<class v>
auto operator<<(ostream &os, const vector<v> &vec)->ostream& {
os << vec[0];
for (size_t i = 1; i < vec.size(); i++) {
os << ' ' << vec[i];
}
os << '\n';
return os;
}
template<class v>
auto operator>>(istream &is, vector<v> &vec)->istream& {
for (auto &i : vec) {
is >> i;
}
return is;
}
template<class v>
auto operator<<(ostream &os, const vector<vector<v>> &vec)->ostream& {
for (auto &i : vec) {
os << i[0];
for (size_t j = 1; j < i.size(); j++) {
os << ' ' << i[j];
}
os << '\n';
}
return os;
}
template<class v>
auto operator>>(istream &is, vector<vector<v>> &vec)->istream& {
for (auto &i : vec) {
for (auto &j : i) {
is >> j;
}
}
return is;
}
const int inf = INT32_MAX >> 1;
int closepower2(int n)
{
return n == 1 ? 1 : 1 << (sizeof(n) * 8 - __builtin_clz(n - 1));
}
int nextpower2(int n)
{
return n == 1 ? 1 : sizeof(n) * 8 - __builtin_clz(n - 1);
}
class segtree_min {
struct segnode {
int content;
int left, right;
segnode(): content(inf), left(0), right(0) {}
segnode(int content): content(content), left(0), right(0) {}
segnode(int content, int left, int right):
content(content), left(left), right(right) {}
int getcontent() const {
return content == inf ? -1 : content;
}
};
vector<segnode> nodes;
vector<int> roots;
size_t alloc;
int n;
int create_leaf(long long v) {
new (&nodes[alloc]) segnode(v);
alloc++;
return alloc - 1;
}
int update_node(int l, int r) {
new (&nodes[alloc]) segnode(min(nodes[l].content, nodes[r].content), l, r);
alloc++;
return alloc - 1;
}
int _update(int i, int l, int r, int f, long long v) {
if (l > f || r < f) {
return i;
}
if (l == f && r == f) {
int now = create_leaf(v);
return now;
}
int mid = (l + r) / 2;
int left = _update(nodes[i].left, l, mid, f, v);
int right = _update(nodes[i].right, mid + 1, r, f, v);
if (nodes[i].left == left && nodes[i].right == right) {
return i;
}
if (nodes[i].left != left) {
return update_node(left, nodes[i].right);
}
return update_node(nodes[i].left, right);
}
long long search(int i, int l, int r, int ql, int qr) {
if (l > qr || r < ql) {
return inf;
}
if (l >= ql && r <= qr) {
return nodes[i].content;
}
int m = (l + r) / 2;
return min(search(nodes[i].left, l, m, ql, qr), search(nodes[i].right, m + 1, r, ql, qr));
}
public:
segtree_min() = delete;
segtree_min(size_t n): nodes(closepower2(n) * 2 + nextpower2(n) * closepower2(n) + closepower2(n)),
roots({0}), alloc(closepower2(n) * 2 - 1), n(closepower2(n) - 1) {
for (size_t i = 0; i < closepower2(n) - 1; i++) {
new (&nodes[i]) segnode(inf, i * 2 + 1, i * 2 + 2);
}
}
void update(int i, long long v) {
int root = _update(roots.back(), 0, n, i, v);
roots.push_back(root);
}
long long query(int l, int r) {
int root = roots[r];
// int root = roots.back();
l--, r--;
return search(root, 0, n, l, r);
}
void print() {
int root = roots.back();
queue<int> q;
q.push(root);
while (!q.empty()) {
int p = q.front();
q.pop();
if (nodes[p].left != 0) {
q.push(nodes[p].left);
q.push(nodes[p].right);
}
cout << nodes[p].getcontent() << ' ';
}
cout << '\n';
}
void print_full() {
int root = roots.back();
queue<int> q;
q.push(root);
while (!q.empty()) {
int p = q.front();
q.pop();
if (nodes[p].left != 0) {
q.push(nodes[p].left);
q.push(nodes[p].right);
}
cout << p << ": " << nodes[p].getcontent() << ' ' << nodes[p].left << ' ' << nodes[p].right << '\n';
}
}
void print_roots() {
for (auto i : roots) {
cout << i << ' ';
}
cout << '\n';
}
void print_all_ver() {
for (auto i : roots) {
queue<long long> q;
q.push(i);
while (!q.empty()) {
int p = q.front();
q.pop();
if (nodes[p].left != 0) {
q.push(nodes[p].left);
q.push(nodes[p].right);
}
cout << nodes[p].getcontent() << ' ';
}
cout << '\n';
}
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<long long> nums(n);
for (auto &i : nums) {
cin >> i;
}
segtree_min seg(n);
map<int, int> dis;
for (size_t i = 0; i < n; i++) {
long long now = inf;
if (dis.find(nums[i]) != dis.end()) {
now = i - dis[nums[i]];
seg.update(dis[nums[i]], now);
} else {
seg.update(i, inf);
}
dis[nums[i]] = i;
}
while (m--) {
int l, r;
cin >> l >> r;
long long ans = seg.query(l, r);
cout << (ans == inf ? -1 : ans) << '\n';
}
}