zoukankan      html  css  js  c++  java
  • 牛客练习赛52 B题【树状数组维护区间和{查询区间和,如果区间元素重复出现则计数一次}】补题ing

    【题目】

    查询区间和,如果区间元素重复出现则计数一次。

    链接:https://ac.nowcoder.com/acm/contest/1084/B

    【题解】

      将询问按r排序,维护每个数最后出现的位置,并用树状数组维护前缀和即可

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 #define int long long
     5 #define lowbit(x) (x&(-x))
     6 #define N 500009
     7 int n,m;
     8 int arr[N];
     9 int ans[N];
    10 int mp[N];
    11 struct str{
    12     int l,r,id;
    13 }st[N];
    14 int c[N];
    15 inline void update(int x,int v){
    16     for(int i=x;i<=n;i+=lowbit(i))  
    17         c[i]+=v;
    18 }
    19 inline int getsum(int x){
    20     int res=0; 
    21     for(int i=x;i;i-=lowbit(i))
    22         res+=c[i]; 
    23     return res;
    24 }
    25 bool cmp(str a,str b){
    26     return a.r<b.r;
    27 }
    28 signed main(){
    29     cin>>n>>m;
    30     memset(mp,0,sizeof(mp));
    31     
    32     for(int i=1;i<=n;i++){
    33         scanf("%lld",&arr[i]);
    34     }
    35     for(int i=1;i<=m;i++){
    36         scanf("%lld%lld",&st[i].l,&st[i].r);
    37         st[i].id=i;
    38     }
    39     sort(st+1,st+1+m,cmp);
    40     int now=1;
    41     for(int i=1;i<=m;i++){
    42         for(int j=now;j<=st[i].r;j++){
    43             if(mp[arr[j]]){
    44                 update(mp[arr[j]],-arr[j]);
    45             }
    46             
    47             update(j,arr[j]);
    48             mp[arr[j]]=j;
    49         }
    50         now=st[i].r+1;
    51         ans[st[i].id]=getsum(st[i].r)-getsum(st[i].l-1);
    52     }
    53     for(int i=1;i<=m;i++){
    54         printf("%lld
    ",ans[i]);
    55     }
    56     return 0;
    57 }

    如果要查询区间不同元素个数:则将代码改为:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 #define int long long
     5 #define lowbit(x) (x&(-x))
     6 #define N 500009
     7 int n,m;
     8 int arr[N];
     9 int ans[N];
    10 int mp[N];
    11 struct str{
    12     int l,r,id;
    13 }st[N];
    14 int c[N];
    15 inline void update(int x,int v){
    16     for(int i=x;i<=n;i+=lowbit(i))  
    17         c[i]+=v;
    18 }
    19 inline int getsum(int x){
    20     int res=0; 
    21     for(int i=x;i;i-=lowbit(i))
    22         res+=c[i]; 
    23     return res;
    24 }
    25 bool cmp(str a,str b){
    26     return a.r<b.r;
    27 }
    28 signed main(){
    29     cin>>n>>m;
    30     memset(mp,0,sizeof(mp));
    31     
    32     for(int i=1;i<=n;i++){
    33         scanf("%lld",&arr[i]);
    34     }
    35     for(int i=1;i<=m;i++){
    36         scanf("%lld%lld",&st[i].l,&st[i].r);
    37         st[i].id=i;
    38     }
    39     sort(st+1,st+1+m,cmp);
    40     int now=1;
    41     for(int i=1;i<=m;i++){
    42         for(int j=now;j<=st[i].r;j++){
    43             if(mp[arr[j]]){
    44                 update(mp[arr[j]],-1);
    45             }
    46             
    47             update(j,1);
    48             mp[arr[j]]=j;
    49         }
    50         now=st[i].r+1;
    51         ans[st[i].id]=getsum(st[i].r)-getsum(st[i].l-1);
    52     }
    53     for(int i=1;i<=m;i++){
    54         printf("%lld
    ",ans[i]);
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    反流技术之IE插件技术研究第一部分
    c# post和接收的实现
    C# post提交表单的例程
    用C#搭建IE BHO勾子, 取表单密码
    复杂的 DataBinding 接受 IList 或 IListSource 作为数据源" 错误原来是自己的笔误
    C#判断ContextMenuStrip右键菜单的来源(从哪个控件弹出来的)
    练习5.1
    示例:实用函数(Utilities)
    闭包
    一个错误
  • 原文地址:https://www.cnblogs.com/pengge666/p/11561498.html
Copyright © 2011-2022 走看看