码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2019-03-10 22:18:21      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:不同   color   set   +=   排序   计算   没有   也会   遇到   

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

我们先考虑一个问题,如何求从[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\n",res[i]);
67     return 0;
68 }

 

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

标签:不同   color   set   +=   排序   计算   没有   也会   遇到   

原文地址:https://www.cnblogs.com/iat14/p/10507586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!