• HDU


    题目链接:Necklace

    题意:

      给出一串珠子,每个珠子有它的value,现在给出n(n<=5e4)个珠子的value(1<=value<=1e6),现在给出m(1<=m<=2e5)个询问,每个询问给出l和r,要求[l,r]区间内所有珠子的value(如果有相同value值的珠子则只计算一次这个珠子的值)。

    题解:

      刚开始看到这题,遇到区间求和就想到了树状数组。但是如何解决区间内相同value值只能计算一次的问题呢?看了题解后发现可以用离线化解决这个问题,我们可以先把所有的询问保存下来,将询问按右端点从小到大排序,然后将所有有重复的value值只保留最后一个位置的值,其他的value值全都减去。因为区间的右端点保证是从小到大的,而可以发现[l,r]这个区间的值就等于所有数保留最后一个出现的数的和(可以自己验证一下)。这里离散化最大的功能就是保证了我们的操作是从小到大的,这样我们前面的操作就不会影响后面的操作。还有这里是要用long long的不然会爆~@。@#

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 const int MAX_N = 1e5+9;
     7 typedef pair<int,int> P;
     8 P q[MAX_N*4];
     9 int q1[MAX_N*4];
    10 int vis[MAX_N*10];
    11 long long vec[MAX_N];
    12 long long res[MAX_N];
    13 long long out[MAX_N*4];
    14 void add(int x,long long num)
    15 {
    16     for(;x<MAX_N;x+=(x&-x))
    17         res[x] += num;
    18 }
    19 long long sum(int x)
    20 {
    21     long long ans = 0;
    22     for(;x>0;x-=(x&-x))
    23         ans += res[x];
    24     return ans;
    25 }
    26 int main()
    27 {
    28     int N,M,T;
    29     cin>>T;
    30     while(T--)
    31     {
    32         cin>>N;
    33         memset(res,0,sizeof(res));
    34         memset(vis,0,sizeof(vis));
    35         for(int i=1;i<=N;i++)
    36         {
    37             scanf("%lld",&vec[i]);
    38             add(i,vec[i]);
    39             if(!vis[vec[i]]) vis[vec[i]] = i;
    40         }
    41         cin>>M;
    42         for(int i=0;i<M;i++)
    43         {
    44             scanf("%d%d",&q1[i],&q[i].first);
    45             q[i].second = i;
    46         }
    47         sort(q,q+M);
    48         int right = 1;
    49         for(int i=0;i<M;i++)
    50         {
    51             for(int j=right;j<=q[i].first;j++)
    52             {
    53                 if(vis[vec[j]] != j)
    54                 {
    55                     add(vis[vec[j]],-vec[j]);
    56                     vis[vec[j]] = j;
    57                 }
    58             }
    59             right = q[i].first;
    60             out[q[i].second] = sum(q[i].first) - sum(q1[q[i].second]-1);
    61         }
    62         for(int i=0;i<M;i++)
    63         {
    64             printf("%lld
    ",out[i]);
    65         }
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    Lucene4.5.1之添加索引、更新索引、删除索引、查找数据
    DWR 2.0.10之简单测试
    SNMP OID列表
    zabbix low-level discovery 监控mysql
    Linux系统负载查询
    MySQL 调优
    Linux 下DNS详解
    C语言计算两个日期间隔天数
    Linux vmstat命令详解
    select函数的详细使用(C语言)
  • 原文地址:https://www.cnblogs.com/doggod/p/8406793.html
Copyright © 2020-2023  润新知