8.17那天我再考场上用莫队A了这题。。。。其实是可以卡掉的。正解是线段树或树状数组。
按照询问的r排序,然后r没向右移动一次,如果这个数曾经出现了,就在这个数原来出现的地方减去这个数,再在当前位置加上这个数。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define maxl 30010
#define maxq 100010
using namespace std;
long long n,m,cnt;
long long a[maxl],b[maxl],ans[maxq];
struct que{long long l,r,num;} q[maxq];
map <long long,int> pre;
bool cmp(const que &x,const que &y)
{
if(x.r==y.r)
return x.l<y.l;
else
return x.r<y.r;
}
void prework()
{
memset(b,0,sizeof(b));
pre.clear();
scanf("%lld",&n);
for(long long i=1;i<=n;i++)
scanf("%lld",&a[i]);
scanf("%d",&m);
for(long long i=1;i<=m;i++)
scanf("%lld%lld",&q[i].l,&q[i].r),q[i].num=i;
sort(q+1,q+1+m,cmp);
}
void add(long long i,long long x)
{
while(i<maxl)
{
b[i]+=x;
i+=i&-i;
}
}
long long sum(long long i)
{
long long s=0;
while(i)
{
s+=b[i];
i-=i&-i;
}
return s;
}
void mainwork()
{
long long r=0;
for(long long i=1;i<=m;i++)
{
while(r<q[i].r)
{
r++;
if(pre[a[r]]!=0)
add(pre[a[r]],-a[r]);
add(r,a[r]);
pre[a[r]]=r;
}
ans[q[i].num]=sum(q[i].r)-sum(q[i].l-1);
}
}
void print()
{
for(long long i=1;i<=m;i++)
printf("%lld\n",ans[i]);
}
int main()
{
long long t;
scanf("%lld",&t);
for(long long i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}