#include<iostream>
#include<vector>
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int Maxn = 1e5 + 6;
struct Node {
int l;
int r;
ll val;
}T[Maxn * 40];
int root[Maxn];
ll arr[Maxn];
vector<int>v;
int n, m;
int cnt = 0;
int built(int &node, int l, int r) {
node = ++cnt;
T[node].val = 0;
if (l == r) return 0;
int mid = (l + r) / 2;
built(T[node].l, l, mid);
built(T[node].r, mid + 1, r);
}
int update(int &node,int last,int be,int en,int i,ll val) {
T[++cnt] = T[last]; //复制一个单独的节点
node = cnt;//***接上节点,十分重要
if (be == en) {
T[node].val = val;
return T[node].val;
}
int mid = (be + en) / 2;
if (i <= mid) update(T[node].l, T[last].l, be, mid, i, val);
else update(T[node].r, T[last].r, mid + 1, en, i, val);
T[node].val = T[T[node].l].val + T[T[node].r].val;
return T[node].val;
}
ll query(int node,int be, int en, int LL, int RR) {//当前节点node l--r,当前区间,,,x--y,所求区间
if (LL <= be && en <= RR) {
return T[node].val;
}
int mid = (be + en) / 2;
ll res = 0;
if(mid >= LL) res += query(T[node].l, be, mid, LL, RR);
if(RR > mid) res+= query(T[node].r, mid + 1, en, LL, RR);
return res;
}
int t;
map<ll, int>ins;
int main() {
scanf("%d", &t);
while (t--) {
ins.clear();
cnt = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &arr[i]);
}
built(root[0], 1, n);
for (int i = 1; i <= n; i++) {
//没出现就直接加上
if (ins[arr[i]] == 0) {
update(root[i], root[i - 1], 1, n, i, arr[i]);
ins[arr[i]] = i;
}
else {
int tmp = 0;//tmp只是一个中介,就像交换数时候的 t 一样
update(tmp, root[i - 1], 1, n, ins[arr[i]], 0);
update(root[i], tmp, 1, n, i, arr[i]);
ins[arr[i]] = i;
}
}
scanf("%d", &m);
for (int i = 0; i < m; i++) {
int x, y;
scanf("%d%d", &x, &y);
ll ans = query(root[y], 1, n, x, y);
printf("%lld\n",ans);
}
}
return 0;
}
https://blog.csdn.net/why932346109/article/details/98955619
这个大佬写的十分详细,我留下了以后准备着复习看吧
画图之后就理解了,太强了!!!
题意:给你一个长度为n的序列,m个询问:询问区间[L,R]中不同的数的和是多少?
大概就是这样,最后附上新垣结衣