[SDOI2009]HH的项链

OJ题号:BZOJ1878、洛谷1972

思路:树状数组离线化。

不难想到,对于一个[l,r]的区间,如果出现了多个相同的颜色,我们可以只关心在区间[l,r]中,该颜色最后一个贝壳。

例如,对于形如{1,2,3,2,1}的项链,当我们询问区间[1,5]时,该项链等同于{0,0,3,2,1}(方便起见,这里用0表示空)。

于是就有了以下的思路:当询问[l,r]时,答案即为区间[l,r]内新出现的贝壳的个数。

显而易见,当新的贝壳出现时,原来的同色贝壳都会失效。

那么问题来了,对于{1,2,3,2,1}这个项链,当我们询问[1,5]时,答案是3;当我们询问[1,3]时,答案也是3,但如果使用上面的方法,我们记录的是{0,0,3,2,1},输出的答案是1。怎么办?

一种思路是使用可持久化数据结构,比如主席树(可持久化线段树)等。然而当时主席树似乎并没有被发明?

这里介绍一种离散化做法。

首先对所有的询问预处理,即以右端点r为关键字进行排序。

建立一个树状数组,记录每个前缀新出现的贝壳的个数。

当然树状数组并不能一次性建好,每次根据当前询问的r,加入位置≤r的所有贝壳(将树状数组中的位置标记为1),并删去相同颜色的贝壳(将树状数组中的位置标记为0)。

然后发现洛谷上能A,在BZOJ上就RE了?

 最后发现的原因:代表颜色的数字不一定是连续的,而且可能会很大(编号为0到1000000之间的整数),所以直接开数组会爆,解决的方法是Hash(不方便)或者Map。

RunID User Problem Result Memory Time Language Code_Length Submit_Time
2084658 skylee 1878 Accepted 4668 kb 1488 ms C++/Edit 1324 B 2017-05-27 17:34:54
 1 #include<map>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<utility>
 5 #include<algorithm>
 6 #define r first
 7 #define l second.first
 8 #define id second.second
 9 typedef std::pair<int,std::pair<int,int> > Q;
10 const int N=50001;
11 int n;
12 class FenwickTree {
13     private:
14         int val[N];
15         int lowbit(const int x) {
16             return x&-x;
17         }
18     public:
19         FenwickTree() {
20             memset(val,0,sizeof val);
21         }
22         void modify(int p,const int x) {
23             while(p<=n) {
24                 val[p]+=x;
25                 p+=lowbit(p);
26             }
27         }
28         int query(int p) {
29             int ans=0;
30             while(p) {
31                 ans+=val[p];
32                 p-=lowbit(p);
33             }
34             return ans;
35         }
36 };
37 FenwickTree tree;
38 int main() {
39     scanf("%d",&n);
40     int a[n+1];
41     for(int i=1;i<=n;i++) {
42         scanf("%d",&a[i]);
43     }
44     int m;
45     scanf("%d",&m);
46     Q q[m];
47     for(int i=0;i<m;i++) {
48         scanf("%d%d",&q[i].l,&q[i].r);
49         q[i].id=i;
50     }
51     std::sort(&q[0],&q[m]);
52     int p=1;
53     std::map<int,int> last;
54     int ans[m];
55     for(int i=0;i<m;i++) {
56         while(p<=q[i].r) {
57             if(last[a[p]]) tree.modify(last[a[p]],-1);
58             tree.modify(last[a[p]]=p,1);
59             p++;
60         }
61         ans[q[i].id]=tree.query(q[i].r)-tree.query(q[i].l-1);
62     }
63     for(int i=0;i<m;i++) printf("%d\n",ans[i]);
64     return 0;
65 }

 

posted @ 2017-05-27 17:14  skylee03  阅读(160)  评论(0编辑  收藏  举报