hdu 3874 树状数组 成段不重复求和
离线处理询问,即先记录下所有询问
用map将当前的值映射到一个下标,如果以前已经映射过了,则在树状数组中取消在上一次的位置的记录
再在当前位置加入当前值,这样的话对于每个询问便可以先更新再查询,离线记录结果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int maxn = 50010;
__int64 c[maxn];
struct node{
int l,r,id;
}p[200010];
map<int,int> hash;
int lowbit(int x){
return x&-x;
}
void update(int x,int d){
for(;x<maxn;x+=lowbit(x))
c[x]+=d;
}
__int64 sum(int x){
__int64 ans=0;
for(;x>0;x-=lowbit(x))
ans+=c[x];
return ans;
}
int cmp(node a,node b){
return a.r<b.r;
}
int a[maxn];
__int64 ans[200010];
int main()
{
int t,i,j,l,r,n;
int q;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
memset(c,0,sizeof(c));
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
int pt=1;
hash.clear();
sort(p+1,p+q+1,cmp);
for(i=1;i<=q;i++)
{
while(pt<=p[i].r)
{
if(hash[a[pt]]!=0)
{
update(hash[a[pt]],-a[pt]);
}
update(pt,a[pt]);
hash[a[pt]]=pt;
pt++;
}
ans[p[i].id]=sum(p[i].r)-sum(p[i].l-1);
}
for(i=1;i<=q;i++)
{
printf("%I64d\n",ans[i]);
}
}
return 0;
}