这题的题意大概是
给出一段长度为(n) 的区间
(q)次询问求 (L)~ (R) 这个区间内 最短的一段区间 (l)~(r)
使得 (oplus_{i=l}^{r} a_j= 0)
(L<=l<r<=r)
诶 离线么?树状数组好像不好做啊 因为大多数人只会单点修改区间修改和差分吧
考虑离线+线段树
我们先记录一个 (sum_i = oplus_{j=1}^i a_j)
那么我们用一个类似桶一样的东西 (pos_i) 记录上一个出现(sum_i) 的位置
显然这题是个单点修改 求区间最小值
考虑移动 右指针 (r)
把询问的右端点为(r) 的存在一起 这样就省下来一个排序
我们要记录 (l) 点对区间的贡献
应该反过来做 考虑 (sum_j) 最后一次出现的位置 (pos_{sum_j})
然后对 (pos_{sum_j}) 进行单点修改 能保证这个肯定对于(pos_{sum_j})这个点来说向右偏移最小的值使得异或和为0
因为移动的是右端点 右端点往右的区间和当前区间是互为独立的 或者换句话说 右端点往右的区间对当前区间是没有贡献的即对答案不会影响
然后直接大力查询 (query(l,r)) 就可以了
#include<bits/stdc++.h>
using namespace std ;
int n , q ;
const int N = 5e5 + 5 ;
int sum[N] ;
vector < pair < int , int > > v[N] ;
int mn[N << 2] ;
int pos[N << 2] ;
int used[N] ;
int ans[N << 1] ;
inline void build(int l , int r , int rt) {
mn[rt] = INT_MAX ;
if(l == r) return ;
int mid = l + r >> 1 ;
build(l , mid , rt << 1) ;
build(mid + 1 , r , rt << 1 | 1) ;
}
inline void change(int x , int l , int r , int rt , int val) {
if(l == r) { mn[rt] = val ; return ; }
int mid = l + r >> 1 ;
if(x <= mid) change(x , l , mid , rt << 1 , val) ;
else change(x , mid + 1 , r , rt << 1 | 1 , val) ;
mn[rt] = min(mn[rt << 1] , mn[rt << 1 | 1]) ;
}
inline int query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return mn[rt] ;
int mid = l + r >> 1 ;
int ans = INT_MAX ;
if(a <= mid) ans = min(ans , query(a , b , l , mid , rt << 1)) ;
if(b > mid) ans = min(ans , query(a , b , mid + 1 , r , rt << 1 | 1 )) ;
return ans ;
}
#define fi first
#define se second
signed main() {
scanf("%d %d" , & n , & q) ;
for(register int i = 1 ; i <= n ; i ++) {
int x ; scanf("%d" , & x) ;
sum[i] = sum[i - 1] ^ x ;
}
for(register int i = 1 ; i <= q ; i ++) {
int l , r , id ; scanf("%d %d" , & l , & r) ; id = i ;
v[r].push_back({l , id}) ;
}
build(1 , n , 1) ;
for(register int i = 1 ; i <= n ; i ++) {
pos[sum[i - 1]] = i ;
int p = pos[sum[i]] ;
if(p && ! used[p]) {
change(p , 1 , n , 1 , i - p + 1) ;
used[p] = 1 ;
}
for ( auto x : v[i] ) ans[x.se] = query(x.fi , i , 1 , n , 1) ;
}
for(register int i = 1 ; i <= q ; i ++) printf("%d
" , ans[i] == INT_MAX ? -1 : ans[i]) ;
return 0 ;
}