题目大意:
下列有 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;
}