zoukankan      html  css  js  c++  java
  • BZOJ 1878 HH的项链 (树状数组+离线)

    题目大意:给你一个序列,求某区间出现不同的数的个数。

    貌似离线树状数组是最好的解法

    先把所有询问挂在它们询问的右端点上

    然后从头到尾遍历这个序列,记录这个位置的值上一次出现的位置

    那么,当遍历到第i位时,如果a[i]在之前出现过,就在它上一次出现的位置-1

    这个操作的意义是,第i位已经有a[i]了,那么上一次出现a[i]的位置已经失去意义

    接着在这个位置+1,更新last[a[i]]。差分操作用树状数组维护

    然后我们遍历以这个位置为结尾的所有询问,用树状数组查前缀和,因为在a[i]相同的位置不会重复打差分,所以query(r)-query(l-1)即为这个询问的答案。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <queue>
     5 #define inf 0x3f3f3f3f
     6 #define ll long long 
     7 #define N 500100
     8 #define maxn 1000000
     9 using namespace std;
    10 //re
    11 int n,m,cte;
    12 int a[N],head[N];
    13 int lst[N*2],sum[N*2];
    14 struct Ques{
    15     int l,r,ans,id;
    16 }ques[N];
    17 struct EDGE{
    18     int to,nxt;
    19 }edge[N];
    20 void edge_add(int u,int v)
    21 {
    22     cte++;
    23     edge[cte].to=v;
    24     edge[cte].nxt=head[u];
    25     head[u]=cte;
    26 }
    27 int cmp1(Ques s1,Ques s2) {return s1.r<s2.r;}
    28 int cmp2(Ques s1,Ques s2) {return s1.id<s2.id;}
    29 void update(int x,int w) {for(int i=x;i<=maxn;i+=(i&(-i)))sum[i]+=w;}
    30 int query(int x) {int ans=0;for(int i=x;i>0;i-=(i&(-i)))ans+=sum[i];return ans;}
    31 
    32 int main()
    33 {
    34     //freopen("data.in","r",stdin);
    35     scanf("%d",&n);
    36     memset(head,-1,sizeof(head));
    37     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    38     scanf("%d",&m);
    39     for(int i=1;i<=m;i++)
    40         scanf("%d%d",&ques[i].l,&ques[i].r),ques[i].id=i;
    41     sort(ques+1,ques+m+1,cmp1);
    42     for(int i=1;i<=m;i++)
    43         edge_add(ques[i].r,i);
    44     for(int i=1;i<=n;i++)
    45     {
    46         if(lst[a[i]]) update(lst[a[i]],-1);
    47         update(i,1),lst[a[i]]=i;
    48         for(int j=head[i];j!=-1;j=edge[j].nxt){
    49             int v=edge[j].to;
    50             ques[v].ans=query(ques[v].r)-query(ques[v].l-1);
    51         }
    52     }
    53     sort(ques+1,ques+m+1,cmp2);
    54     for(int i=1;i<=m;i++) printf("%d
    ",ques[i].ans);
    55     return 0;
    56 }
  • 相关阅读:
    学习日报
    阅读笔记2
    学习日报
    记账本开发7
    记账本开发6
    学习日报
    记账本开发5
    今日总结
    今日总结
    家庭记账本7
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9697029.html
Copyright © 2011-2022 走看看