题意:求给定去接内不重复数字的和
做法: 图灵树还是没有学到....
只要先记录每个询问,然后按照右边界排序,还需要记录每个位置之前距离它最近那个与他相等的元素的位置。再树状数组做一下。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lowbit(x) ((x)&-(x))
typedef __int64 LL;
const int LMT = 30003;
using namespace std;
struct __line
{
int l, r, pos;
bool operator < (const __line &y)const
{
return r < y.r;
}
}line[100003];
struct __copy
{
int num, pos;
bool operator < (const __copy &y)const
{
if(num != y.num) return num < y.num;
return pos < y.pos;
}
}a_copy[LMT];
int a[LMT], n, vis[LMT];
LL sum[LMT], ans[100002];
void update(int op, int x)
{
while(x <= n)
{
sum[x] += op;
x += lowbit(x);
}
}
LL query(int x)
{
LL res = 0;
while(x > 0)
{
res += sum[x];
x -= lowbit(x);
}
return res;
}
int main(void)
{
int q, i, j, T;
scanf("%d", &T);
while(T--)
{
memset(vis, -1, sizeof(vis));
memset(sum, 0, sizeof(sum));
scanf("%d", &n);
for(i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
a_copy[i].num = a[i];
a_copy[i].pos = i;
}
scanf("%d", &q);
for(i = 0; i < q; ++i)
{
scanf("%d%d", &line[i].l, &line[i].r);
line[i].pos = i;
}
sort(line, line + q);
sort(&a_copy[1], &a_copy[1] + n);
for( i = 2; i <= n; ++i)
if (a_copy[i].num == a_copy[i - 1].num)
vis[a_copy[i].pos] = a_copy[i - 1].pos;
for(i = 1, j = 0; i <= n && j < q; ++i)
{
update(a[i], i);
if (vis[i] != -1) update(-a[i], vis[i]);
while(j < q && line[j].r == i)
{
ans[line[j].pos] = query(line[j].r) - query(line[j].l - 1);
++j;
}
}
for(i = 0; i < q; ++i)printf("%I64d\n", ans[i]);
}
return 0;
}