zoukankan      html  css  js  c++  java
  • 【树状数组+离线查询】HDU 3333 Turing Tree

    https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/H

    【题意】

    给定一个数组,查询任意区间内不同数字之和。

    (n<=30000,Q<=100000,每个数字<=1 000 000 000)

    【思路】

    要算任意区间内不同数字之和,如果我们从左到右依次处理,每次只保留最右边出现的数字,处理以当前数字为右端点的查询,就能做到“不同数字之和”,即不重不漏。因此我们要离线处理查询,按记录每个数作为右端点的所有查询区间。这里要用到vector记录固定右端点后每个所有查询区间的左端点和查询ID,要用map或unorderd_map记录每个数之前出现的位置(要把那个位置的删掉)

    【Accepted】

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<map>
     9 #include<unordered_map>
    10 using namespace std;
    11 const int maxn=1e5+3;
    12 typedef long long ll;
    13 int n,m;
    14 vector<pair<int,int> > p[maxn];
    15 map<ll,int> pre;
    16 
    17 ll tree[maxn];
    18 ll a[maxn];
    19 ll ans[maxn];
    20 void init()
    21 {
    22     memset(ans,0,sizeof(ans));
    23     for(int i=1;i<=n;i++)
    24     {
    25         tree[i]=0LL;
    26     }
    27     pre.clear();
    28 }
    29 int lowbit(int x)
    30 {
    31     return x&(-x);
    32 }
    33 void add(int k,ll x)
    34 {
    35     while(k<=n)
    36     {
    37         tree[k]+=x;
    38         k+=lowbit(k);
    39     }
    40 }
    41 
    42 ll query(int k)
    43 {
    44     ll res=0LL;
    45     while(k)
    46     {
    47         res+=tree[k];
    48         k-=lowbit(k);
    49     }
    50     return res;
    51 }
    52 ll query(int l,int r)
    53 {
    54     return query(r)-query(l-1);
    55 }
    56 int main()
    57 {
    58     int T;
    59     scanf("%d",&T);
    60     while(T--)
    61     {
    62         scanf("%d",&n);
    63         init();
    64         for(int i=1;i<=n;i++)
    65         {
    66             cin>>a[i];    
    67             p[i].clear();    
    68         }    
    69         scanf("%d",&m);
    70         int u,v;
    71         for(int i=1;i<=m;i++)
    72         {
    73             scanf("%d%d",&u,&v);
    74             p[v].push_back(make_pair(u,i));
    75         }    
    76         for(int i=1;i<=n;i++)
    77         {
    78             if(pre.count(a[i]))
    79             {
    80                 add(pre[a[i]],-a[i]);
    81             }
    82             pre[a[i]]=i;
    83             add(i,a[i]);
    84             int sz=p[i].size();
    85             for(int k=0;k<sz;k++)
    86             {
    87                 ans[p[i][k].second]=query(p[i][k].first,i);
    88             }
    89         }
    90         for(int i=1;i<=m;i++)
    91         {
    92             cout<<ans[i]<<endl;
    93         }
    94     }
    95     return 0;
    96 }
    View Code



  • 相关阅读:
    php -- 魔术方法 之 对象输出 : __toString()
    php -- each()、list()
    php -- 魔术方法、魔术常量 简单介绍
    webbench
    md5sum/opensll md5
    shopt
    MD5
    print显示特定的数据格式
    gdb调试4--回退
    字符串化#、拼接字符##和可变参数宏(...和_ _VA_ARGS_ _)
  • 原文地址:https://www.cnblogs.com/itcsl/p/7132540.html
Copyright © 2011-2022 走看看