/* 题意为查找区间去重后的和 用树状数组离线处理 将所有查询以右端点从小到大排序 按此顺序边去重边查询 前面的去重就不会影响到后面的结果了 */ #include <iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<ctime> using namespace std; #define N 50009 int n,m; struct INV { int s,e,num; }inv[200009];//询问区间s为起点,e为终点 int first[N*20],pre[N],tmp[N];//pre[i]表示第i个数上次出现的位置,i位置前无与tmp[i]相同的数则为-1 long long ans[200009]; bool cmp(INV x,INV y)//以区间右侧从小到大排序 { if(x.e!=y.e)return x.e<y.e; return x.s<y.s; } //刚学到的输入方式,能优化时间哦~~ int nextInt() { char c; while (c = getchar(), c < '0' || c > '9'); int r = c - '0'; while (c = getchar(), c >= '0' && c <= '9') r = r * 10 + c - '0'; return r; } //以下为树状数组模版 //****************************************************** long long ar[N]; int lowb(int t){return t&(-t);} void add(int i,int v) { for(;i<N;ar[i]+=v,i+=lowb(i)); } long long sum(int i) { long long s=0; for(;i>0;s+=ar[i],i-=lowb(i)); return s; } //*********************************************************** void init() { scanf("%d",&n); memset(ar,0,sizeof(ar)); memset(first,-1,sizeof(first)); for(int i=1;i<=n;i++) { //scanf("%d",&tmp[i]); tmp[i]=nextInt(); pre[i]=first[tmp[i]]; first[tmp[i]]=i; add(i,tmp[i]); } scanf("%d",&m); for(int i=0;i<m;i++) { //scanf("%d%d",&inv[i].s,&inv[i].e); inv[i].s=nextInt(); inv[i].e=nextInt(); if(inv[i].s>inv[i].e)swap(inv[i].s,inv[i].e); inv[i].num=i; } } void solve() { sort(inv,inv+m,cmp); int r=0; //r的左侧已经去重完毕 for(int i=0;i<m;i++) { for(int j=inv[i].e;j>r;j--)//讲要查询的未去重的地段去重 { if(pre[j]!=-1) add(pre[j],-tmp[j]); } r=inv[i].e; ans[inv[i].num]=sum(inv[i].e)-sum(inv[i].s-1); } for(int i=0;i<m;i++) printf("%I64d\n",ans[i]); } int main() { int Case; scanf("%d",&Case); while(Case--) { init(); solve(); } return 0; }