题意:
给你一个长度为
n
n
n序列
a
i
a_i
ai,然后给你
m
m
m个询问,每个询问给出
l
,
r
l,r
l,r,问你区间
[
l
,
r
]
[l,r]
[l,r]内各不相同的数的和是多少。
思路:
其实之前碰到过类似思路的问题了,如果
c
o
d
e
f
o
r
c
e
s
703
D
codeforces703D
codeforces703D,求区间内出现偶数次的数的异或和,就需要我们求出区间内不同的数的异或和为多少。
同理这个题需要我们维护的是区间内出现不同的数的和,类似于那题,可以观察到这道题目里面并没有要求我们在线修改,那么我们就可以通过把区间按右端点从小到大排个序,这样就能保证操作的正确性,当前统计的答案一定是在合法的区间内的,避免出现那种一开始要查
r
r
r很大,接着
r
r
r又很小的情况。这种反复横跳的情况。
每次更新操作,先把当前位置的值上一次出现的位置清空,再更新当前区间,即可保证答案的正确性。
m
a
p
map
map维护位置,线段树更新查询即可。
不知道为什么 N N N开 3 e 4 3e4 3e4会 w a . . . . . . . . . . . wa........... wa...........
#include <bits/stdc++.h>
using namespace std;
#define pb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
#define CLOSE std::ios::sync_with_stdio(false)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int N = 1e5 + 10;
const int M = 1e5 + 10;
int n,m,tot;
ll a[N],b[N],tree[N<<2],ans[N];
//类似于询问区间内出现偶数次的数的异或和的思路 重点是学会这种思路
//因为那个要求区间内所有出现过得不同的数的个数
struct Q {
int l,r,id;
bool operator < (const Q& a) const {
return r < a.r;
}
}q[M];
void pushup(int rt) { tree[rt] = tree[lson] + tree[rson]; }
void build(int rt,int l,int r) {
if(l == r) { tree[rt] = 0; return ; }
int mid = (l + r) >> 1;
build(lson,l,mid);build(rson,mid+1,r);
pushup(rt);
}
void modify(int rt,int l,int r,int p,ll v) {
if(l == r) {
tree[rt] += v; return ;
}
int mid = (l + r) >> 1;
if(p <= mid) modify(lson,l,mid,p,v);
else modify(rson,mid+1,r,p,v);
pushup(rt);
}
ll query(int rt,int l,int r,int L,int R) {
if(l >= L && r <= R) return tree[rt];
int mid = (l + r) >> 1;
ll ans = 0;
if(L <= mid) ans += query(lson,l,mid,L,R);
if(R > mid) ans += query(rson,mid+1,r,L,R);
return ans;
}
std::map<ll,int>pre;
int main() {
int T;scanf("%d",&T);
while(T--) {
scanf("%d",&n);
pre.clear();
for(int i = 1;i <= n;i ++) {
scanf("%lld",&a[i]);
}
build(1,1,n);
scanf("%d",&m);
for(int i = 1;i <= m;i ++) {
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id = i;
}
sort(q + 1,q + 1 + m);
int L,R = 1;
for(int i = 1;i <= m;i ++) {
while(R <= q[i].r) {
if(!pre[a[R]]) {
modify(1,1,n,R,a[R]);
pre[a[R]] = R;
}
else {
modify(1,1,n,pre[a[R]],-a[R]);
modify(1,1,n,R,a[R]);
pre[a[R]] = R;
}
R++;
}
L = q[i].l;
ans[q[i].id] = query(1,1,n,L,R);
}
for(int i = 1;i <= m;i ++) {
printf("%lld\n",ans[i]);
}
}
return 0;
}