这个题其实还算常规,就是后面求和的时候把前面的最近的重复值去掉就行,我用的树状数组,然后离散化了一下。PS这个题跟3874差不多,可以说3874是这个题简化版
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=3e4+1000;
const int maxm=maxn*4;
const int maxe=1e5+100;
struct Query
{
int l;
int r;
int id;
bool operator < (const Query &a)const
{
if(a.r==r)
return l<a.l;
return r<a.r;
}
}q[maxe];
int n,m,cnt,pre[maxn],index[maxn],a[maxn],b[maxn];
long long t[maxn],ans[maxe];
int lowbit(int x)
{
return x&(-x);
}
void Update(int x,long long val)
{
for(;x<=n;t[x]+=val,x+=lowbit(x));
}
long long Sum(int x)
{
if(x==0)
return 0;
long long ans=0;
for(;x>0;ans+=t[x],x-=lowbit(x));
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(index,-1,sizeof(index));
memset(t,0,sizeof(t));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
cnt=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++)
a[i]=lower_bound(b,b+cnt,a[i])-b;
for(int i=1;i<=n;i++)
{
pre[i]=index[a[i]];
index[a[i]]=i;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q,q+m);
int now=1;
for(int i=0;i<m;i++)
{
while(now<=q[i].r)
{
if(pre[now]!=-1)
Update(pre[now],-b[a[now]]);
Update(now,b[a[now]]);
now++;
}
ans[q[i].id]=Sum(q[i].r)-Sum(q[i].l-1);
}
for(int i=0;i<m;i++)
printf("%I64d\n",ans[i]);
}
return 0;
}