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.

97 lines
2.6 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 <unordered_map>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 30010, M = 100010;
/*
图灵树的来历原来是这个。。经典的线段树离线所有查询右端点排序的题目吧。。
所有询问右端点排序后从小到大扫过去线段树维护序列区间和用一个map记录各个数最右边出现的位置
一遇到一个数就把之前位置消除并更新当前位置,相当于把各个数尽量向右移动。。
*/
struct Node {
int l, r;
LL sum;
} tr[N << 2];
struct Question {
int l, r, id;
const bool operator<(const Question &t) const {
return r < t.r;
}
} q[M];
int 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);
}
void modify(int u, int x, int d) {
if (tr[u].l == tr[u].r) {
tr[u].sum += (LL)d;
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if (x <= mid) modify(u << 1, x, d);
if (x > mid) modify(u << 1 | 1, x, d);
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;
}
int main() {
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
int T;
cin >> T;
while (T--) {
unordered_map<int, int> b;
memset(ans, 0, sizeof ans);
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
// 按右端点排序
sort(q + 1, q + 1 + m);
// 构建线段树
build(1, 1, n);
for (int i = 1, j = 1; i <= m; i++) { // i枚举每个查询,j枚举的是原始数组数据
while (j <= q[i].r) { // 在空间内的逐个进入,并不断修改最后的值
if (b.count(a[j])) modify(1, b[a[j]], -a[j]);
modify(1, j, a[j]);
b[a[j]] = j++;
}
ans[q[i].id] = query(1, q[i].l, q[i].r);
}
for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
}
return 0;
}