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