1878: [SDOI2009]HH的项链

1878: [SDOI2009]HH的项链

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 4420  Solved: 2199
[Submit][Status][Discuss]

Description

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一
段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一
个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只
好求助睿智的你,来解决这个问题。

Input

第一行:一个整数N,表示项链的长度。 
第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 
第三行:一个整数M,表示HH询问的个数。 
接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
N ≤ 50000,M ≤ 200000。

Output

M行,每行一个整数,依次表示询问对应的答案。

Sample Input

6
1 2 3 4 3 5
3
1 2
3 5
2 6

Sample Output

2
2
4

 

//离线算法的话,比较好写,树状数组,或线段树维护一个前缀和

在线算法听说是主席树,目前还不会,以后会了,一定更

离线树状数组,思路是,先对贝壳数组模拟一个链表,nex[i] 记录每个位置右边最近的与该位置贝壳种类相同的贝壳的位置。

然后,pos[i] 记录 i 种类的贝壳最靠左的位置,然后,对每个存在种类的贝壳的最靠左位置(就是pos[i]),建一个树状数组,位置上有最靠左的贝壳就是 1 ,否则是0,这样是为了统计区间内的种类数!

然后,所有查询按左端点排序,枚举左端点,靠前面的链表更新树状数组,求前缀和。

其实感觉最大的耗时在于对询问的排序。。。mlog(m)

 1 /**************************************************************
 2     Problem: 1878
 3     User: happy_code
 4     Language: C++
 5     Result: Accepted
 6     Time:1780 ms
 7     Memory:8908 kb
 8 ****************************************************************/
 9  
10 #include <iostream>
11 #include <stdio.h>
12 #include <string.h>
13 #include <algorithm>
14 using namespace std;
15 #define MXN 50005
16 #define MXM 200005
17 struct Que
18 {
19     int l,r;
20     int id;
21     int ans;
22 }q[MXM];
23  
24 int n,m;
25 int a[MXN];
26 int pos[1000005];
27 int nex[MXN];
28 int tree[MXN];
29  
30 int lowbit(int x){return x&(-x);}
31 bool cmp1(const Que &a,const Que &b)
32 {
33     return a.l<b.l;
34 }
35 bool cmp2(const Que &a,const Que &b)
36 {
37     return a.id<b.id;
38 }
39  
40 void update(int x,int k)
41 {
42     for (int i=x;i<=n;i+=lowbit(i))
43         tree[i]+=k;
44 }
45  
46 int query(int x)
47 {
48     int res=0;
49     for (int i=x;i>0;i-=lowbit(i))
50         res+=tree[i];
51     return res;
52 }
53  
54 int main()
55 {
56     scanf("%d",&n);
57     for (int i=1;i<=n;i++)
58         scanf("%d",&a[i]);
59     for (int i=n;i>0;i--)
60     {
61         nex[i]=pos[a[i]];
62         pos[a[i]]=i;
63     }
64     for (int i=0;i<1000005;i++) //初始化
65         if (pos[i]) update(pos[i],1);
66  
67  
68     scanf("%d",&m);
69     for (int i=0;i<m;i++)
70     {
71         scanf("%d%d",&q[i].l,&q[i].r);
72         q[i].id=i;
73     }
74     sort(q,q+m,cmp1);
75  
76     int l=1;
77     for (int i=0;i<m;i++)
78     {
79         while (l<q[i].l)
80         {
81             if (nex[l]) update(nex[l],1);
82             l++;
83         }
84         q[i].ans = query(q[i].r)-query(q[i].l-1);
85     }
86  
87     sort(q,q+m,cmp2);
88     for (int i=0;i<m-1;i++)
89         printf("%d\n",q[i].ans);
90     printf("%d\n",q[m-1].ans);
91     return 0;
92 }
View Code

 

posted @ 2017-08-03 22:07  happy_codes  阅读(183)  评论(0编辑  收藏  举报