#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 ",ans); } } return 0; }
https://blog.csdn.net/why932346109/article/details/98955619
这个大佬写的十分详细,我留下了以后准备着复习看吧
画图之后就理解了,太强了!!!
题意:给你一个长度为n的序列,m个询问:询问区间[L,R]中不同的数的和是多少?
大概就是这样,最后附上新垣结衣