对Q个询问按照右端点离线,每次查询只需要判断那个数是否已经在树状数组里面了
对于30000个数据全部存在数组里,去重,二分查询位置判断是否存在
#include<cstring> #include<string> #include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<map> #include<cstdlib> #include<cmath> #include<vector> //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f #define maxn 30005 vector<long long>v; int pos[maxn]; long long ans[maxn*4]; long long a[maxn]; long long c[maxn]; int l[maxn*4],r[maxn*4],e[maxn*4]; int n; int lowbit(int x) { return x&(-x); } void update(int x,long long val) { while(x<=n) { c[x]+=val; x+=lowbit(x); } } long long query(int x) { long long sum=0; while(x>0) { sum+=c[x]; x-=lowbit(x); } return sum; } bool cmp(int a,int b) { if(r[a]==r[b]) return l[a]<l[b]; return r[a]<r[b]; } int main() { int T_T; scanf("%d",&T_T); while(T_T--) { v.clear(); scanf("%d",&n); memset(c,0,sizeof c); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); v.push_back(a[i]); } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); memset(pos,-1,sizeof pos); int m; scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d%d",&l[i],&r[i]); e[i]=i; } sort(e,e+m,cmp); int cnt=1; for(int i=0;i<m;i++) { int t=e[i]; while(cnt<=r[t]) { int p=lower_bound(v.begin(),v.end(),a[cnt])-v.begin(); if(pos[p]==-1) { update(cnt,v[p]); pos[p]=cnt; } else { update(pos[p],-v[p]); update(cnt,v[p]); pos[p]=cnt; } cnt++; } ans[t]=query(r[t])-query(l[t]-1); } for(int i=0;i<m;i++) { printf("%lld\n",ans[i]); } } return 0; }