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");
} 
京公网安备 11010502036488号