CF522D
Closest Equals
https://ac.nowcoder.com/acm/problem/110867
分析
考虑只有一个区间有一对相同的值时才有答案。所以我们可以把所以点对存下来,这样是 。考虑如果有多个相同的话,其实只需要储存相邻的两个即可,这样就只有 级别的点对了。再考虑如果有一个大区间包含了一个小区间证明,如何任何时候大区间不可能是最优解,最后做一次区间最小值就好了。
代码
#include<bits/stdc++.h> using namespace std; int read() { int x = 0,f = 0;char ch = getchar(); while(!isdigit(ch)) {if(ch == '-')f = 1;ch = getchar();} while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();} return f ? -x : x; } const int N = 5e5 + 100; int A[N],st[N][21]; map<int,int> s; int tot,L[N],R[N],m,n,cnt; int ask(int l,int r) { int k = log2(r - l + 1); return min(st[l][k],st[r-(1<<k)+1][k]); } int main() { n = read();m = read(); for(int i = 1;i <= n;i++) { A[i] = read(); if(s[A[i]]) { int j = s[A[i]]; s[A[i]] = i; if(cnt && L[cnt] >= j) continue; L[++cnt] = j;R[cnt] = i; } else s[A[i]] = i; } for(int i = 1;i <= cnt;i++) st[i][0] = R[i] - L[i]; for(int j = 1;(1 << j) <= cnt;j++) { for(int i = 1;i + (1<<j) <= cnt + 1;i++) { st[i][j] = min(st[i][j-1],st[i+(1<<j-1)][j-1]); } } while(m--) { int l = read(),r = read(); l = lower_bound(L+1,L+cnt+1,l) - L; r = upper_bound(R+1,R+cnt+1,r) - R - 1; if(l > r) {puts("-1");continue;} printf("%d\n",ask(l,r)); } }