题目链接:点我啊╭(╯^╰)╮
题目大意:
F
(
l
,
r
)
=
A
l
&
A
l
+
1
&
.
.
.
&
A
r
F(l, r) = A_l \& A_{l+1} \& ... \& A_{r}
F(l,r)=Al&Al+1&...&Ar
S
(
l
,
r
)
=
{
F
(
a
,
b
)
∣
m
i
n
(
l
,
r
)
≤
a
≤
b
≤
m
a
x
(
l
,
r
)
}
S(l, r) = \{F(a, b) | min(l, r) ≤ a ≤ b ≤ max(l, r)\}
S(l,r)={F(a,b)∣min(l,r)≤a≤b≤max(l,r)}
Q
Q
Q 次查询
l
l
l 和
r
r
r,求
S
(
l
,
r
)
S(l, r)
S(l,r)
解题思路:
一个数字连续作与操作,不同数字最多出现
l
o
g
log
log 个
因此对每个
a
i
a_i
ai,记录它往左不停作与操作出现的不同数字
这里我们要查询
S
(
l
,
r
)
S(l, r)
S(l,r),也就是以
r
r
r 为右端点,做与操作的不同数字且产生过程都在
l
l
l 右端
联想到主席树求区间不同数字的操作
这里就可以在记录
a
i
a_i
ai 往左不停作与操作出现的不同数字 的同时
维护产生这些数字的左端点的最大值
这个最大值
m
a
x
max
max 就是我们查询
S
(
l
,
r
)
S(l, r)
S(l,r) 时,
l
l
l 必须要
≤
m
a
x
≤max
≤max
因为所有的不同数字最多
n
l
o
g
n
nlogn
nlogn 个,因此直接用
m
a
p
map
map 维护最大值即可
时间复杂度:
O
(
n
l
o
g
2
n
+
q
l
o
g
n
)
O(nlog^2n +qlogn)
O(nlog2n+qlogn)
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 1e5 + 5;
int T, n, q, lans, tot, root[maxn];
int t[maxn*300], ls[maxn*300], rs[maxn*300];
map <int, int> mp, tmp, las;
void update(int &rt, int pre, int pos, int c, int l, int r) {
if(l>pos || r<pos) return;
rt = ++tot;
t[rt] = t[pre] + c;
ls[rt] = ls[pre], rs[rt] = rs[pre];
if(l == r) return;
int mid = l + r >> 1;
update(ls[rt], ls[pre], pos, c, l, mid);
update(rs[rt], rs[pre], pos, c, mid+1, r);
}
int query(int rt, int L, int R, int l, int r) {
if(l>R || r<L) return 0;
if(l>=L && r<=R) return t[rt];
int mid = l + r >> 1, ret = 0;
ret += query(ls[rt], L, R, l, mid);
ret += query(rs[rt], L, R, mid+1, r);
return ret;
}
signed main() {
scanf("%d", &n);
for(int i=1, x; i<=n; ++i) {
scanf("%d", &x);
root[i] = root[i-1];
mp[x] = i; tmp.clear();
for(auto j : mp) {
int fi = j.first, se = j.second;
tmp[fi & x] = max(tmp[fi & x], se);
}
for(auto j : tmp) {
int fi = j.first, se = j.second;
if(las[fi] == se) continue;
update(root[i], root[i], las[fi], -1, 1, n);
las[fi] = se;
update(root[i], root[i], las[fi], 1, 1, n);
}
mp.swap(tmp);
}
scanf("%d", &q);
while(q--) {
int l, r;
scanf("%d%d", &l, &r);
l = (l ^ lans) % n + 1;
r = (r ^ lans) % n + 1;
if(l > r) swap(l, r);
printf("%d\n", lans = query(root[r], l, r, 1, n));
}
}