SPOJ - DQUERY: D-query 离线处理 + 树状数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ - DQUERY: D-query 离线处理 + 树状数组相关的知识,希望对你有一定的参考价值。

题目链接:https://vjudge.net/problem/SPOJ-DQUERY

 

题意:给定数字序列,求任意区间内的不同数字的个数

 

解法:用树状数组维护 1 ~ i 的区间内不同数字个数的前缀和,首要解决的问题就是同一区间内相同数字统计时相互影响的问题,解决方法如下:离线存储查询的区间,对查询区间按照左端点排序,这样可以优先处理左边的           元素;然后预处理出每一元素下一跳到相同元素的 nxt[]; 这样随着坐标轴指针 l 的移动,l 左边的元素将不会产生任何影响,因为所产生的影响会在前缀和的做差运算中抵消;只需要对 l 指针左区间的元素的下一跳的位           置进行 add + 1 操作,从而更新当前查询区间的信息。 

 

BIT代码实现:

技术分享
 1 //190ms    19.5MB
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int N = 30010;
 6 const int M = 200010;
 7 int a[N], bit[N];
 8 
 9 void init() {
10     memset(bit, 0, sizeof(bit));
11 }
12 
13 int lowbit(int x) {
14     return x & -x;
15 }
16 
17 void add(int x, int val) {
18     while(x < N) {
19         bit[x] += val;
20         x += lowbit(x);
21     }
22 }
23 
24 int sum(int x) {
25     int ret = 0;
26     while(x > 0) {
27         ret += bit[x];
28         x -= lowbit(x);
29     }
30     return ret;
31 }
32 
33 struct Query{
34     int l, r, p;
35     bool operator < (const Query& p)const{
36         return l < p.l;
37     }
38 } query[M];
39 int n, q;
40 map<int, int> mp;
41 int nxt[N], ans[M];
42 
43 int main()
44 {
45     scanf("%d", &n);
46     mp.clear();
47     init();
48     for (int i = 1; i <= n; ++ i) {
49         scanf("%d", &a[i]);
50         if(mp.find(a[i]) == mp.end()) {
51             mp[a[i]] = i;
52             add(i, 1);
53         }
54     }
55     mp.clear();
56     for (int i = n; i >= 1; -- i) {
57         if(mp.find(a[i]) == mp.end()) nxt[i] = n + 1;
58         else nxt[i] = mp[a[i]];
59         mp[a[i]] = i;
60     }
61     scanf("%d", &q);
62     for (int i = 1; i <= q; ++ i) {
63         scanf("%d%d", &query[i].l, &query[i].r);
64         query[i].p = i;
65     }
66     sort(query+1, query+1+q);
67     int pp = 1;
68     for (int i = 1; i <= q; ++ i) {
69         while(pp<=n && pp < query[i].l) add(nxt[pp++], 1);
70         ans[query[i].p] = sum(query[i].r) - sum(query[i].l-1);
71     }
72     for (int i = 1; i <= q; ++ i) printf("%d\n", ans[i]);
73     return 0;
74 }
View Code

 

以上是关于SPOJ - DQUERY: D-query 离线处理 + 树状数组的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ DQUERY - D-query

SPOJ DQUERY D-query(主席树)

SPOJ DQUERY D-query(莫队基础题)

Spoj 3267 DQUERY - D-query

[SPOJ DQUERY] D-query(树状数组,离线)

SPOJ - DQUERY: D-query 离线处理 + 树状数组