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:
parent
337b443085
commit
48a13b9262
261
VK Cup 2015 - Qualification Round 1/D. Closest Equals.cpp
Normal file
261
VK Cup 2015 - Qualification Round 1/D. Closest Equals.cpp
Normal 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';
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user