Closest Equals
题目大意:
给你一串数,有次询问,每次求问一个区间,问在区间内最近的两个相同的数的距离是多少
分析:
第一反应就是记录一下这个值上一次出现的位置,这就可以记录一次答案了
然后可以构造出一个新的序列,因为当某两个可行的数在另外两个可行的数内时,外面的数是没有贡献的
然后就可以找到第一个的, 然后再找到最后一个
这就构成了一个新的可行区间
那么如果找到的新的那么这就是无解的, 直接输出
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e5 + 10; const int mod = 1e9 + 7; inline int __read() { int x(0), t(1); char o (getchar()); while (o < '0' || o > '9') { if (o == '-') t = -1; o = getchar(); } for (; o >= '0' && o <= '9'; o = getchar()) x = (x << 1) + (x << 3) + (o ^ 48); return x * t; } int n, m, cnt, cur; int a[maxn], d[maxn], p[maxn], f[maxn][25]; int __prev[maxn], __last[maxn], __log[maxn] = {-1}; map <int, int> Vis; inline int _lower_bound(int x) { int l(1), r(cur), ans(cur + 1); while (l <= r) { int mid((l + r) >> 1); if (__prev[mid] < x) l = mid + 1; else ans = mid, r = mid - 1; } return ans; } inline int _upper_bound(int x) { int l(1), r(cur), ans(cur + 1); while (l <= r) { int mid((l + r) >> 1); if (__last[mid] <= x) l = mid + 1; else ans = mid, r = mid - 1; } return ans - 1; } inline int min__(int a, int b) { return a < b ? a : b; } signed main() { n = __read(), m = __read(); for (int i(1); i <= n; ++i) { int temp = __read(); if (!Vis[temp]) Vis[temp] = ++cnt; a[i] = Vis[temp]; int j = p[a[i]]; p[a[i]] = i; if (__prev[cur] >= j) continue; __prev[++cur] = j, __last[cur] = i, d[cur] = i - j; } for (int i(1); i <= cur; ++i) f[i][0] = d[i], __log[i] = __log[i >> 1] + 1; for (int j(1); (1 << j) <= cur; ++j) for (int i(1); i + (1 << j) - 1 <= cur; ++i) f[i][j] = min__(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); while (m--) { int x = _lower_bound(__read()), y = _upper_bound(__read()); if (y < x) { puts("-1"); continue; } int len = __log[y - x + 1]; printf ("%d\n", min__(f[x][len], f[y - (1 << len) + 1][len])); } system("pause"); }