Holy crap... Memory limit gallore, I had to make a LOT of optimizations on this one, and it just barely worked...
262 lines
5.2 KiB
C++
262 lines
5.2 KiB
C++
#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';
|
|
}
|
|
}
|