链接
题意:
n
n
个数个查询,每次查询在
[l,r]
[
l
,
r
]
中满足
ai=aj时j−i
a
i
=
a
j
时
j
−
i
的最大值。
思路:
对整个数组分块,设块的大小为
sz
s
z
,总共有
tot
t
o
t
块,那么记
f[i][j]
f
[
i
]
[
j
]
:从第
i
i
块到第块满足
ax=ay
a
x
=
a
y
时
y−x
y
−
x
的最大值。这样对于区间
[l,r]
[
l
,
r
]
的查询,在两端的直接暴力查找,对于在中间的直接是
f[l/sz+1][r/sz−1]
f
[
l
/
s
z
+
1
]
[
r
/
s
z
−
1
]
。时间复杂度有点高,
O(nn−−√logn)
O
(
n
n
log
n
)
, 开个输入挂进去。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 1e5 + 10;
using namespace std;
int a[maxn], b[1110][1110], vis[maxn];
vector<int> vec[maxn];
int n, m, k, l, r, block_size;
inline int solve(int flag, int L, int R, int l, int r) {
int ans = 0;
for(int i = L; i <= R; i++) {
int x = a[i];
if(flag == 1) {
int i1 = upper_bound(vec[x].begin(), vec[x].end(), r) - vec[x].begin() - 1;
if(i1 >= 0 && vec[x][i1] >= l) ans = max(ans, abs(i - vec[x][i1]));
} else {
int i2 = lower_bound(vec[x].begin(), vec[x].end(), l) - vec[x].begin();
if(i2 != vec[x].size() && vec[x][i2] <= r) ans = max(ans, abs(i - vec[x][i2]));
}
}
return ans;
}
inline int query(int l, int r) {
int b1 = l / block_size;
int b2 = r / block_size, ans = 0;
if(b1 == b2) return solve(1, l, r, l, r);
///处理两端
int l1 = (b1 + 1) * block_size - 1;
int l2 = b2 * block_size;
ans = max(ans, solve(1, l, l1, l, r));
ans = max(ans, solve(0, l2, r, l, r));
///处理块与块之间
if(b1 + 1 <= b2 - 1) ans = max(ans, b[b1 + 1][b2 - 1]);
return ans;
}
const int MAX = 10000;
char buf[MAX], *ps = buf, *pe = buf + 1;
inline void rnext() {
if(++ps == pe) pe = (ps = buf) + fread(buf, sizeof(char), sizeof(buf) / sizeof(char), stdin);
}
template <class T>
inline bool in(T &ans) {
ans = 0;
T f = 1;
if(ps == pe) return false;//EOF
do{
rnext();
if('-' == *ps) f = -1;
} while(!isdigit(*ps) && ps != pe);
if(ps == pe) return false;//EOF
do {
ans = (ans<<1)+(ans<<3)+*ps-48;
rnext();
} while(isdigit(*ps) && ps != pe);
ans *= f;
return true;
}
int main() {
while(in(n)) {
in(m); in(k);
for(int i = 0; i < maxn; i++) vec[i].clear();
memset(b, 0, sizeof b);
for(int i = 0; i < n; i++) {
in(a[i]);
vec[a[i]].push_back(i);
}
block_size = 100;
for(int i = 0; i < n; i += block_size) {
int imax = 0;
memset(vis, -1, sizeof vis);
for(int j = i; j < n; j++) {
if(vis[a[j]] == -1) vis[a[j]] = j;
else imax = max(imax, j - vis[a[j]]);
int &bs = b[i / block_size][j / block_size];
bs = max(bs, imax);
}
}
while(k--) {
in(l); in(r); l--; r--;
printf("%d\n", query(l, r));
}
}
return 0;
}