• HDU 3333 树状数组离线查询


     题目大意:

    询问区间内不同种类的数的数值之和

    这里逐个添加最后在线查询,会因为相同的数在区间内导致冲突

    我们总是希望之后添加的数不会影响前面,那么我们就在添加到第i个数的时候,把所有在1~i 的区间的询问全部处理完成即可

    对于之前的冲突,我们可以不断记录上一次冲突的位置,给当前的前缀和添加一个当前的val

    对于上一次之前的前缀和要减去那个val就不会产生冲突了(之所以离线也是因为这个地方,如果后面的数添加完成,那么之前可能减去那个位置的数就导致区间查询出错)

    所以将询问区间优先右排序就行了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <map>
     6 using namespace std;
     7 
     8 #define LL long long
     9 #define lowbit(x) x&(-x)
    10 #define M 100010
    11 #define N 30005
    12 char s[6];
    13 int n , m , a[N];
    14 LL sum[N] ;
    15 map<int ,int> mp;
    16 
    17 struct Query{
    18     int l , r , id;
    19     bool operator<(const Query &m) const{
    20         return r<m.r || (r==m.r&&l<m.l);
    21     }
    22 }qu[M];
    23 
    24 LL rec[M];
    25 
    26 void add(int x , int v)
    27 {
    28     while(x<=n){
    29         sum[x] = sum[x]+v ;
    30         x+=lowbit(x);
    31     }
    32 }
    33 
    34 LL query(int x){
    35     LL ret = 0;
    36     while(x>0) ret = ret+sum[x] , x-=lowbit(x);
    37     return ret;
    38 }
    39 
    40 int main()
    41 {
    42     //freopen("in.txt" , "r" , stdin);
    43     int T ;
    44     scanf("%d" , &T);
    45     while(T--){
    46         scanf("%d" , &n);
    47         memset(sum , 0 , sizeof(sum));
    48         for(int i=1 ; i<=n ; i++)
    49             scanf("%d" , &a[i]);
    50 
    51         scanf("%d" , &m);
    52         for(int i=0 ; i<m ; i++){
    53             int l , r;
    54             scanf("%d%d" , &l , &r);
    55             qu[i] = (Query){l , r , i};
    56         }
    57         sort(qu , qu+m);
    58         int cur = 0;
    59         mp.clear();
    60         for(int i=1 ; i<=n ; i++){
    61             if(mp.find(a[i]) == mp.end()){
    62                 add(i , a[i]);
    63                 mp.insert(make_pair(a[i] , i));
    64             }else{
    65                 add(i , a[i]);
    66                 add(mp[a[i]] , -a[i]);
    67                 mp[a[i]] = i;
    68             }
    69             while(qu[cur].r == i){
    70                 rec[qu[cur].id] = query(qu[cur].r)-query(qu[cur].l-1);
    71                 cur++;
    72             }
    73         }
    74         for(int i=0 ; i<m ; i++) printf("%I64d
    " , rec[i]);
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    多项式插值取模哈希标记法
    AC自助机
    [OIBH] 糖果盒(Candy Box)——又一个最大子矩形
    windows phone 之ListBox数据绑定
    WP学习笔记
    为TextArea添加maxlength属性
    让整个网页(LOGO图片)色调全部变灰的方法(CSS写法)
    JS调试加断点
    Container.ItemIndex 获取到行的序号
    c# Invoke 与 BeginInvoke
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4754259.html
Copyright © 2020-2023  润新知