2 6 1 2 3 4 3 5 3 1 2 3 5 2 6 6 1 1 1 2 3 5 3 1 1 2 4 3 5
3 7 14 1 3 6
按区间的右端点排序,离线查询各个区间,在查询之前 删除扫到的点的前一个位置出现的点。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
using namespace std;
typedef long long LL;
const int maxn = 50005;
const int MAX = 0x3f3f3f3f;
const int mod = 1000000007;
int t, n, m, A, B, in[maxn], last[maxn], pre[1000005];  //last记录每个点的前一个相同的点的位置,不存在记录为-1.
LL sum[maxn<<2], ans[200005];
struct C {
    int l, r, num;
}a[200005];
bool cmp (C x, C y) {
    return x.r < y.r;
}
void up(int o) {
    sum[o] = sum[o<<1] + sum[o<<1|1];
}
void build(int o, int l, int r) {
    if(l == r) sum[o] = in[l];
    else {
        int m = (l+r) >> 1;
        build(lson);
        build(rson);
        up(o);
    }
}
void update(int o, int l, int r) {
    if(l == r) {
        sum[o] = 0;
        return ;
    }
    int m = (l+r) >> 1;
    if(A <= m) update(lson);
    else update(rson);
    up(o);
}
LL query(int o, int l, int r) {
    if(A <= l && r <= B) return sum[o];
    int m = (l+r) >> 1;
    LL res = 0;
    if(A <= m) res += query(lson);
    if(m < B ) res += query(rson);
    return res;
}
void Ini() {
    memset(pre, -1, sizeof(pre));
    memset(last, -1, sizeof(last));
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &in[i]);
        if(pre[ in[i] ] != -1) {
            last[i] = pre[ in[i] ];
            pre[ in[i] ] = i;
        } else pre[ in[i] ] = i;
    }
}
int main()
{
    scanf("%d", &t); while (t--) {
        Ini();
        scanf("%d", &m);
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &a[i].l, &a[i].r);
            a[i].num = i;
        }
        sort(a+1, a+m+1, cmp);
        build(1, 1, n);
        int fr = 1;
        for(int i =1; i <= m; i++) {
            for(int j = fr; j <= a[i].r; j++)
                if(last[j] != -1) {
                    A = last[j];
                    update(1, 1, n);
                }
            A = a[i].l;
            B = a[i].r;
            ans[ a[i].num ] = query(1, 1, n);
            fr = a[i].r+1;
        }
        for(int i = 1; i <= m; i++) printf("%I64d\n", ans[i]);
    }
    return 0;
}
HDU 3874 Necklace (线段树单点更新+区间查询+离线操作),布布扣,bubuko.com
HDU 3874 Necklace (线段树单点更新+区间查询+离线操作)
原文地址:http://blog.csdn.net/u013923947/article/details/38514205