HDU 3874

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84000185

题目大意:

        下列有 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;
}

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/84000185
hdu
今日推荐