You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <unordered_map>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 30010, M = 100010;
typedef pair<int, int> PII;
// 线段树结构体
struct Node {
int l, r;
LL sum; // 区间和
} tr[N << 2];
int n, m; // n个数字的原始数列m次询问
int a[N]; // 原始数组
LL ans[M]; // 问题答案
void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(int u, int l, int r) {
tr[u] = {l, r};
int mid = (l + r) >> 1;
if (l == r) return;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u); // 套路其实本题不需要pushup
}
void modify(int u, int x, int v) {
if (tr[u].l == tr[u].r) {
tr[u].sum += v;
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if (x <= mid) modify(u << 1, x, v);
if (x > mid) modify(u << 1 | 1, x, v);
pushup(u);
}
LL query(int u, int l, int r) {
if (l <= tr[u].l && tr[u].r <= r) return tr[u].sum;
LL ans = 0;
int mid = (tr[u].l + tr[u].r) >> 1;
if (l <= mid) ans += query(u << 1, l, r);
if (r >= mid + 1) ans += query(u << 1 | 1, l, r);
return ans;
}
/*
参考答案:
1
5
6
3
6
*/
int main() {
#ifndef ONLINE_JUDGE
freopen("HDU3333.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
int T;
cin >> T;
while (T--) {
// 本题关键词:区间离线查询
unordered_map<int, int> b;
vector<PII> q;
memset(ans, 0, sizeof ans);
memset(tr, 0, sizeof tr);
cin >> n;
// 构建线段树
build(1, 1, n);
for (int i = 1; i <= n; i++) cin >> a[i];
cin >> m;
// ① 记录离线查询,三个要素:序号,左端点,右端点
for (int i = 1; i <= m; i++) {
int l, r;
cin >> l >> r;
q[i] = {l, r};
}
// 通过单点修改,修改线段树的统计信息
for (int i = 1; i <= n; i++) {
// 根据值利用HASH表找出此值原来的位置
// 如果有相同值出现则旧位置上减去a[i],然后更新HASH在新位置上+a[i]
if (b.count(a[i])) modify(1, b[a[i]], -a[i]);
b[a[i]] = i;
modify(1, i, a[i]);
}
for (int i = 1; i <= m; i++)
ans[i] = query(1, q[i].first, q[i].second);
// 输出m次询问的结果
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
}
return 0;
}