luogu P1972 [SDOI2009]HH的项链 树状数组

Posted iat14

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P1972 [SDOI2009]HH的项链 树状数组相关的知识,希望对你有一定的参考价值。

之前只做过分块做法,补一下树状数组做法。

我们先考虑一个问题,如何求从[1,x]这一区间内元素不同的个数?显然我们只要从到到位,遇到一个新的元素,就在对应位置+1,然后使用树状数组求前缀和即可。

这里我们需要去求[x,y],所求区间的左端点也会发生变化。我们先按照[1,x]的方法预处理出这个前缀和数组。我们考虑对询问区间按照左端点排序。然后对于当前的区间[x0,y0],query(y0) - query(x0 - 1)与正确答案相比有所区别,是因为有些元素在x0左侧计算过了,而在这段区间中,对应第一次出现的位置没有+1。我们考虑能不能弥补这个错误呢。我们预处理出nxt[i],表示与位置i元素相同的右侧最近元素的下标。这样子,比如上一个区间为[x1,y1],下一个区间为[x2,y2],那么我们就让[x1,x2)这段区间中的每一个i的nxt[i]位置都对应+1。如果nxt[i]在[x1,x2)内,则不会对以后的答案造成影响,如果nxt[i]在[x2,]后,则显然修正了这个错误,并且在[i,x2)这段区间中,不会再有相同的元素了。

忘记了树状数组的lowbit x & (-x)必须有括号。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 struct qry
 6 {
 7     int l,r,id;
 8     friend bool operator < (qry a,qry b)
 9     {
10         return a.l < b.l;
11     }
12 } vec[510000];
13 int n,m;
14 int num[510000],nxt[510000],hav[1100000],res[510000],sum[510000];
15 int lowbit(int x)
16 {
17     return x & (-x);
18 }
19 void tre_insert(int x,int val)
20 {
21     for (int i = x;i <= n;i += lowbit(i))
22         sum[i] += val;
23 }
24 int tre_qry(int x)
25 {
26     int tot = 0;
27     for (int i = x;i;i -= lowbit(i))
28         tot += sum[i];
29     return tot;
30 }
31 int main()
32 {
33     scanf("%d",&n);
34     for (int i = 1;i <= n;i++) 
35         scanf("%d",&num[i]);
36     scanf("%d",&m);
37     for (int i = 1;i <= m;i++)
38     {
39         scanf("%d%d",&vec[i].l,&vec[i].r);
40         vec[i].id = i;
41     }
42     sort(vec + 1,vec + m + 1);
43     for (int i = 1;i <= n;i++)
44         if (hav[num[i]] == 0)
45         {
46             hav[num[i]] = 1;
47             tre_insert(i,1);
48         }
49     memset(hav,0,sizeof(hav));
50     for (int i = n;i >= 1;i--)
51     {
52         if (hav[num[i]] == 0)
53             nxt[i] = n + 1;
54         else
55             nxt[i] = hav[num[i]];
56         hav[num[i]] = i;
57     } 
58     int t = 1;
59     for (int i = 1;i <= m;i++)
60     {    
61         for (;t <= vec[i].l - 1;t++)
62             tre_insert(nxt[t],1);
63         res[vec[i].id] = tre_qry(vec[i].r) - tre_qry(vec[i].l - 1);
64     }
65     for (int i = 1;i <= m;i++)
66         printf("%d
",res[i]);
67     return 0;
68 }

 

以上是关于luogu P1972 [SDOI2009]HH的项链 树状数组的主要内容,如果未能解决你的问题,请参考以下文章

luogu P1972 [SDOI2009]HH的项链 树状数组

题解 P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链

洛谷 P1972 [SDOI2009]HH的项链

题解P1972 [SDOI2009]HH的项链 - 树状数组