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

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

代码如下:

#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;    

}

你可能感兴趣的:(树状数组)