题解
题目大意 给你n个数字 问你区间内不同元素的和
将讯问离线处理 按照右端点排序 遍历每个位置用一个数组记录每个数值的出现 如果没出现过则在线段树中出现位置标记出现 如果出现则删除上次线段树中的标记并更新标记
对于每个查询当遍历到查询右端点时区间求和则为答案
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 3e4 + 10;
const int MAXQ = 1e5 + 10;
int a[MAXN], vis[MAXN];
ll ans[MAXQ];
vector<int> dz;
struct node2
{
int l, r;
int num;
bool operator < (const node2 &oth)
{
return this->r < oth.r;
}
}q[MAXQ];
struct node
{
int l, r;
ll v;
}tre[MAXN * 4];
inline void PushUp(int x)
{
tre[x].v = tre[x << 1].v + tre[x << 1 | 1].v;
}
void Build(int x, int l, int r)
{
tre[x].l = l, tre[x].r = r, tre[x].v = 0;
if (l == r)
return;
else
{
int m = l + r >> 1;
Build(x << 1, l, m);
Build(x << 1 | 1, m + 1, r);
}
}
void Update(int x, int p, ll v)
{
int l = tre[x].l, r = tre[x].r;
if (l == r)
tre[x].v += v;
else
{
int m = l + r >> 1;
if (m >= p)
Update(x << 1, p, v);
else
Update(x << 1 | 1, p, v);
PushUp(x);
}
}
ll Query(int x, int pl, int pr)
{
int l = tre[x].l, r = tre[x].r;
if (pl <= l && r <= pr)
return tre[x].v;
else
{
int m = l + r >> 1;
ll v = 0;
if (m >= pl)
v += Query(x << 1, pl, pr);
if (m < pr)
v += Query(x << 1 | 1, pl, pr);
return v;
}
}
int Dis(int v)
{
return lower_bound(dz.begin(), dz.end(), v) - dz.begin();
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
while (T--)
{
memset(vis, 0, sizeof(vis));
dz.clear();
dz.push_back(-INF);
int N, Q;
cin >> N;
for (int i = 1; i <= N; i++)
scanf("%d", &a[i]), dz.push_back(a[i]);
sort(dz.begin(), dz.end());
dz.erase(unique(dz.begin(), dz.end()), dz.end()); //离散化值
cin >> Q;
for (int i = 1; i <= Q; i++)
scanf("%d%d", &q[i].l, &q[i].r), q[i].num = i;
sort(q + 1, q + Q + 1);
Build(1, 1, N);
int j = 1;
for (int i = 1; i <= N; i++) //遍历数列
{
int k = vis[Dis(a[i])];
if (k) //出现过
Update(1, k, -a[i]); //取消上次出现位置标记
Update(1, i, a[i]); //在当前位置标记新数字的值
vis[Dis(a[i])] = i;
while (j <= Q && q[j].r == i) //答案右端点等于当前位置
ans[q[j].num] = Query(1, q[j].l, i), j++; //查询区间和
}
for (int i = 1; i <= Q; i++)
printf("%lld\n", ans[i]);
}
return 0;
}