洛谷P1972 HH的项链【树状数组】

题目https://www.luogu.org/problemnew/show/P1972

题意:给定一个长度为n的序列,数字表示珠子的种类。m次查询每次询问给定区间内珠子的种类数。

思路:可以说是运用了前缀和的思想吧。从前到后的去处理查询,而对于某一个查询区间,如果某一个种类出现了多次的话我们只需要计算最后一次出现。

用query(x)表示1~x区间内的种类数,其中对每个种类我们只标记最后一次出现。也就是说顺序遍历的时候如果又出现了就把前面的清空,标记当前位置。

如果查询的区间是l~r那么答案就是query(r) - query(l - 1)。

所以首先需要把查询按照右端点从小到大排序。每次只需要更新上一次右端点到这一次右端点这一段区间,同时要标记每一个种类最近一次出现的位置,用于清空。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<cmath> 
 9 #include<stack>
10 #include<queue>
11 #include<iostream>
12 
13 #define inf 0x3f3f3f3f
14 using namespace std;
15 typedef long long LL;
16 typedef pair<int, int> pr;
17 
18 int n, m;
19 const int maxn = 5e5 + 5;
20 struct node{
21     int l, r, id, ans;
22 }q[maxn];
23 int neck[maxn];
24 int sum[maxn << 2];
25 const int maxnum = 1e6 + 5;
26 int pos[maxnum];
27 
28 bool cmp(node a, node b)
29 {
30     return a.r < b.r; 
31 }
32 
33 bool cmp1(node a, node b)
34 {
35     return a.id < b.id;
36 }
37 
38 
39 void add(int rt, int val)
40 {
41     while(rt <= n){
42         sum[rt] += val;
43         rt += (rt & -rt);
44     }
45 }
46 
47 int query(int rt)
48 {
49     int ans = 0;
50     while(rt){
51         ans += sum[rt];
52         rt -= (rt & -rt);
53     }
54     return ans;
55 }
56 
57 int main()
58 {
59     scanf("%d", &n);
60     for(int i = 1; i <= n; i++){
61         scanf("%d", &neck[i]);
62     }
63     scanf("%d", &m);
64     for(int i = 0; i < m; i++){
65         scanf("%d%d", &q[i].l, &q[i].r);
66         q[i].id = i;
67     }
68     sort(q, q + m, cmp);
69     
70     int nxt = 1;
71     for(int i = 0; i < m; i++){
72         int r = q[i].r;
73         for(int j = nxt; j <= r; j++){
74             if(pos[neck[j]]){
75                 add(pos[neck[j]], -1);
76             }
77             add(j, 1);
78             pos[neck[j]] = j;
79         }
80         nxt = r + 1;
81         q[i].ans = query(q[i].r) - query(q[i].l - 1);
82     }
83     sort(q, q + m, cmp1);
84     for(int i = 0; i < m; i++){
85         printf("%d
", q[i].ans);
86     }
87     return 0;
88 }
原文地址:https://www.cnblogs.com/wyboooo/p/11120884.html