1878: [SDOI2009]HH的项链(离线+树状数组||在线主席树)

1878: [SDOI2009]HH的项链

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 8511  Solved: 4099
[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
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <iomanip>
 6 #include <sstream>
 7 #include <vector>
 8 #include <map>
 9 using namespace std;
10 const int maxn=5*1e4+5;
11 const int maxm=2*1e5+2;
12 map<int,int> ma;
13 int cnt[maxn],arr[maxn],ans[maxm];
14 int n,x,y,m;
15 struct Node{ int x,y,id; }A[maxm];
16 bool cmp(Node a,Node b){ return a.y<b.y; }  //按照右边的进行排序
17 
18 int lowbits(int x) { return x&-x; }
19 void updata(int x,int value){
20     while(x<=maxn){   //树状数组下标不能从0开始
21         cnt[x]+=value;
22         x+=lowbits(x);
23     }
24 }
25 int query(int x){    //x是下标的位置
26     int res=0;
27     while(x>0){
28         res+=cnt[x];
29         x-=lowbits(x);
30     }
31     return res;
32 }
33 
34 int main(){
35     scanf("%d",&n);
36     for(int i=1;i<=n;i++)  scanf("%d",&arr[i]);
37     scanf("%d",&m);
38     for(int i=1;i<=m;i++)  scanf("%d%d",&A[i].x,&A[i].y),A[i].id=i;    //离线
39     sort(A+1,A+1+m,cmp);
40     int L=1;
41     for(int i=1;i<=m;i++){
42         for(int j=L;j<=A[i].y;j++){
43             if(ma[arr[j]]!=0) updata(ma[arr[j]],-1);   //如果前面有过消除前面的影响
44             updata(j,1);   //更新
45             ma[arr[j]]=j;   //更改下标的位置
46         }
47         L=A[i].y+1;
48         ans[A[i].id]=query(A[i].y)-query(A[i].x-1);
49     }
50     for(int i=1;i<=m;i++) printf("%d
",ans[i]);
51     return 0;
52 }
View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int maxn=5*1e4+5;
 7 const int maxm=2*1e5+5;
 8 int n,m,x,y,cnt;
 9 int arr[maxn],root[maxn],ma[1000006];
10 struct Node{ int l,r,sum; }A[maxn*32];
11 inline int read(){
12     int x=0,f=1;
13     char ch=getchar();
14     while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
15     while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); }
16     return x*f;
17 }
18 inline void write(int x){
19     if(x<0) putchar('-'),x=-x;
20     if(x>9) write(x/10);
21     putchar(x%10+48);
22 }
23 void updata(int l,int r,int &now,int pre,int pos,int value){
24     A[++cnt]=A[pre],now=cnt,A[cnt].sum+=value;
25     if(l==r) return;
26     int mid=l+r>>1;
27     if(mid>=pos) updata(l,mid,A[now].l,A[pre].l,pos,value);
28     else updata(mid+1,r,A[now].r,A[pre].r,pos,value);
29 }
30 int query(int l,int r,int pre,int now,int L,int R){
31     if(L<=l&&R>=r) return A[now].sum-A[pre].sum;
32     else{
33         int mid=l+r>>1;
34         if(L>mid) return query(mid+1,r,A[pre].r,A[now].r,L,R);
35         else if(R<=mid) return query(l,mid,A[pre].l,A[now].l,L,R);
36         else return query(l,mid,A[pre].l,A[now].l,L,mid)+query(mid+1,r,A[pre].r,A[now].r,mid+1,R);
37     }
38 }
39 
40 int main(){
41     n=read();
42     for(int i=1;i<=n;i++) arr[i]=read();
43     for(int i=1;i<=n;i++){
44         if(ma[arr[i]]==0) updata(1,n,root[i],root[i-1],i,1);
45         else{
46             int temp=0;
47             updata(1,n,temp,root[i-1],ma[arr[i]],-1);
48             updata(1,n,root[i],temp,i,1);
49         }
50         ma[arr[i]]=i;
51     }
52     m=read();
53     for(int i=1,d1,d2;i<=m;i++){
54         d1=read(),d2=read();
55         write(query(1,n,root[d1-1],root[d2],d1,d2));
56         putchar('
');
57     }
58     return 0;
59 }
View Code
原文地址:https://www.cnblogs.com/qq-1585047819/p/11409475.html