luogu1972 HH的项链(树状数组)

无修改、询问区间种类数的问题可以很容易地用树状数组解决

我们先给询问按右端点排序,然后推着做,每次让a[i]++,表示i处新增了一个种类

但是这样会和前面的有重复,我们只要记下每个种类上次在哪里出现过,当这次又出现了,把前面的那次减掉就可以了

每次处理完之后,就可以计算所有右端点为i的区间的答案,就是这个区间右端点的前缀和减去左端点-1的前缀和

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define ll long long
 4 using namespace std;
 5 const int maxn=5e5+10,maxm=1e6+10;
 6 
 7 inline ll rd(){
 8     ll x=0;char c=getchar();int neg=1;
 9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
11     return x*neg;
12 }
13 
14 int N,M,tr[maxn];
15 int col[maxn],lst[maxm],ans[maxn];
16 struct Q{
17     int l,r,i;
18 }que[maxn];
19 
20 inline int lowbit(int x){return x&(-x);}
21 inline void add(int x,int y){
22     for(;x<=N;x+=lowbit(x)) tr[x]+=y;
23 }
24 inline int query(int x){
25     int re=0;for(;x;x-=lowbit(x)) re+=tr[x];return re;
26 }
27 
28 inline bool cmp(Q a,Q b){
29     return a.r<b.r;
30 }
31 
32 int main(){
33     int i,j,k;
34     N=rd();
35     for(i=1;i<=N;i++) col[i]=rd();
36     M=rd();
37     for(i=1;i<=M;i++){
38         que[i].l=rd(),que[i].r=rd(),que[i].i=i;
39     }sort(que+1,que+M+1,cmp);
40     for(i=1,j=1;i<=N;i++){
41         if(lst[col[i]]) add(lst[col[i]],-1);
42         add(i,1);lst[col[i]]=i;
43         for(;que[j].r==i;j++){
44             ans[que[j].i]=query(i)-query(que[j].l-1);
45         }
46     }
47     for(i=1;i<=M;i++) printf("%d\n",ans[i]);
48     return 0;
49 }

 

posted @ 2018-09-20 16:47  Ressed  阅读(102)  评论(0编辑  收藏  举报