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");
}