zoukankan      html  css  js  c++  java
  • HDU 3874 Necklace(树状数组+离线处理)

     

    题目大意

     

    有一串长度为 n(1≤n50000) 的项链,项链上每块石头都有一个价值,在计算项链上一段连续石头的价值和的时候,相同价值的只计算一次

    现在给你 m(1≤m≤200000) 个询问,每个询问要查询一段连续石头 [L, R] (1≤L≤R≤n)的价值和

     

    做法分析

     

    先把所有的查询保存,然后按照查询区间的右端点由小到大排序,然后离线处理:


    对于一个具体的石头的价值 val,由于我们是按照查询的右端点从小到大排序的,我们当然就希望这个价值出现的位置越靠后(编号越大)越好了,这样就能够保证我们在查询一段区间的和的时候不会算漏了,也就是说,只保留每个价值最靠后的那一块石头,不断的向后加石头更新就行了,具体的说就是这样做的:

            每加一块石头(编号是 id),看这个石头的 val 是否出现过,如果没有出现过,直接加进去就行,然后 last[val]=id

            如果出现过,要先把 last[val] 这个位置的值减去 val,然后在更新,接着给 last[val] 更新:last[val]=id

            如果当前的这块石头是某个查询 [L, R] 的右端点,那么,这个时候直接查询 [L, R] 这段区间的和就行

    当然,我们也可以把按照左端点从大到小排序,不过这样的话,我们就得倒着扫石头了

     

    参考代码

    HDU 3874
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 typedef __int64 LL;
     9 const int N=50006;
    10 
    11 struct Node
    12 {
    13     int L, R, id;
    14     inline void init(int a, int b, int c)
    15     {
    16         L=a, R=b, id=c;
    17     }
    18 
    19     inline bool operator <(const Node &temp) const
    20     {
    21         if(R==temp.R) return L<temp.L;
    22         else return R<temp.R;
    23     }
    24 } op[200006];
    25 int t, n, m, last[1000006], data[N];
    26 LL BIT[N];
    27 
    28 void update(int pos, int val)
    29 {
    30     for(; pos<N; pos+=pos&(-pos)) BIT[pos]+=val;
    31 }
    32 
    33 LL query(int pos)
    34 {
    35     LL sum=0;
    36     for(; pos>0; pos-=pos&(-pos)) sum+=BIT[pos];
    37     return sum;
    38 }
    39 
    40 LL ans[200006];
    41 
    42 int main()
    43 {
    44     scanf("%d", &t);
    45     for(int ca=1; ca<=t; ca++)
    46     {
    47         scanf("%d", &n);
    48         for(int i=1; i<=n; i++)
    49         {
    50             scanf("%d", &data[i]);
    51             last[data[i]]=-1;
    52         }
    53         scanf("%d", &m);
    54         for(int i=0, a, b; i<m; i++)
    55         {
    56             scanf("%d%d", &a, &b);
    57             if(a>b) swap(a, b);
    58             op[i].init(a, b, i);
    59         }
    60         sort(op, op+m);
    61         memset(BIT, 0, sizeof BIT);
    62         for(int i=0, u=1; i<m; i++)
    63         {
    64             for(; u<=op[i].R; u++)
    65             {
    66                 if(last[data[u]]!=-1) update(last[data[u]], -data[u]);
    67                 last[data[u]]=u;
    68                 update(u, data[u]);
    69             }
    70             ans[op[i].id]=query(op[i].R)-query(op[i].L-1);
    71         }
    72         for(int i=0; i<m; i++) printf("%I64d\n", ans[i]);
    73     }
    74     return 0;
    75 }

    题目链接 & AC通道

    HDU 3874 Necklace

  • 相关阅读:
    给你一个长度为 n 的数组,其中只有一个数字出现了大于等于 n/2 次,问如何使用优秀的 时空复杂度快速找到这个数字。
    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现偶数次。找出那个只出现了一次的元素。
    python虚拟环境配置
    测试环境配置
    使用ELK Stack收集kubernetes集群内的应用日志
    vue 禁止遮罩层下的页面滑动
    vue 把 java 传过来的流文件 转成apk、xls等
    vue 中使用 webSocket 收发数据, 增加 " 心跳机制 " 保持连接.
    webstrom 根据当前编辑文件定位左侧目录
    MySQL 8.0新特性详解(转)
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3042291.html
Copyright © 2011-2022 走看看