HDU 3874

题目大意:

        下列有 t 组数据,每组数据 n 个数字,m次询问,每次询问会输入区间 l r ,求l , r 内不同数字之和

 

首先,问题来了,输入的数字存在重复,这样的话单纯的树状数组就没法解决了,但是看了一下输出结果,并不是每次输出都要求输入询问就立刻给出结果,而是输入全部询问后按顺序给出结果,那么就对这一串数字进行一下离散化了,但是如果一次询问过后就离散化一部分,下一部分就会出问题,所以不如先把询问进行一下储存、排序。

按照 从左到右顺序 挨个区间离散化,这样就不会相互干扰,之后只要按顺序输出结果就可以了,这里的离散我用了map 容器,出现过的进行标记,然后 add( id ,-val ) 这样问题就解决了。

 

 

不得不说又张了张见识。

 

以下为AC代码

 

 

 

 

 

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long int
using namespace std;
const int maxn = 50010;
int n,m;
int lowbit(int x)
{
    return x&(-x);
}
ll sum[maxn];
ll a[maxn];
struct node
{
    int l,r,id;
}nd[200005];
void add(int i,ll val)
{
    while(i<=maxn)
    {
        sum[i]+=val;
        i += lowbit(i);
    }
}
ll query(int i)
{
    ll s=0;
    while(i>0)
    {
        s += sum[i];
        i -= lowbit(i);
    }
    return s;
}
bool cmp(node a,node b)
{
    return a.r<b.r;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
      scanf("%d",&m);
      for(int i=1;i<=m;i++)
      {
          scanf("%d%d",&nd[i].l,&nd[i].r);
          nd[i].id = i;
      }
      sort(nd+1,nd+1+m,cmp);
      map<int ,int> mp;
      int k=1;
      ll cnt[200005];
      memset(sum,0,sizeof(sum));
      for(int i=1;i<=m;i++)
      {
          while(k<=nd[i].r)
          {
              ll temp = a[k];
              if(mp[temp]!=0)
                 add(mp[temp],-temp);
              add(k,temp);
              mp[temp]=k;
              k++;
          }
          cnt[nd[i].id]=query(nd[i].r)-query(nd[i].l - 1);
      }
      for(int i=1;i<=m;i++)
        printf("%lld\n",cnt[i]);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值