您的位置:首页 > 其它

HDU-3874 Necklace 树状数组+离线处理

2012-08-11 11:13 211 查看
这题是要求一段区间内的不重复的数字之和。我们通过对询问区间的右端点进行排序,然后记录每一数字的上一次的出现的位置,由于询问都是不回溯的那么就可以线性的更新了。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 50005
using namespace std;

typedef long long int Int64;

int N, M, seq[MAXN], last[1000005];

Int64 ans[200005], c[MAXN];

int lowbit(int x)
{
return x & -x;
}

void modify(int x, int val)
{
for (int i = x; i <= N; i += lowbit(i)) {
c[i] += val;
}
}

Int64 sum(int x)
{
Int64 ret = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
ret += c[i];
}
return ret;
}

struct Node
{
int a, b, no;
bool operator < (Node temp) const
{
return b < temp.b;
}
}q[200005];

int main()
{
int T, ptr;
scanf("%d", &T);
while (T--) {
memset(last, 0, sizeof (last));
memset(c, 0, sizeof (c));
scanf("%d", &N);
ptr = 1;
for (int i = 1; i <= N; ++i) {
scanf("%d", &seq[i]);
}
scanf("%d", &M);
for (int i = 1; i <= M; ++i) {
scanf("%d %d", &q[i].a, &q[i].b);
if (q[i].a > q[i].b) {
int t = q[i].a;
q[i].a = q[i].b;
q[i].b = t;
}
q[i].no = i;
}
sort(q+1, q+M+1);
for (int i = 1; i <= M; ++i) {
while (ptr <= q[i].b) {
if (last[seq[ptr]]) {
modify(last[seq[ptr]], -seq[ptr]);
}
last[seq[ptr]] = ptr;
modify(ptr, seq[ptr]);
++ptr;
}
ans[q[i].no] = sum(q[i].b) - sum(q[i].a-1);
}
for (int i = 1; i <= M; ++i) {
printf("%I64d\n", ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: