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