hdu 3333 树状数组
思路:定义一个map容器用来记录数ai上次出现的位置。将查询区间按右边界升序进行排序,当插入第i个数ai时,pre[ai]+1---->i的区间就会多一个不同的数,其值就是ai,那么可以用update(pre[ai]+1,ai)来保存,但又不能影响i之后的位置,故用update(i,-ai)来消除。每次对于右边界时i的查询区间,只要对其左边界求和就行了,即Sum(qt[i].l)。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #define Maxn 40010 #define lowbit(x) (x&(-x)) using namespace std; __int64 C[Maxn],n,num[Maxn],ans[Maxn*3]; map<int ,int> pre; struct QT{ int l,r,i; int operator <(const QT &temp) const { return r<temp.r; } }qt[Maxn*3]; __int64 Sum(int pos) { __int64 sum=0; while(pos) { sum+=C[pos]; pos-=lowbit(pos); } return sum; } void update(int pos,__int64 val) { while(pos<=n) { C[pos]+=val; pos+=lowbit(pos); } } int main() { int t,q,i,j; scanf("%d",&t); while(t--) { pre.clear(); memset(C,0,sizeof(C)); scanf("%I64d",&n); for(i=1;i<=n;i++) scanf("%I64d",num+i); scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%d%d",&qt[i].l,&qt[i].r); qt[i].i=i; } sort(qt+1,qt+1+q); int j=1; for(i=1;i<=n;i++) { update(pre[num[i]]+1,num[i]); update(i+1,-num[i]); pre[num[i]]=i; while(qt[j].r==i) { ans[qt[j].i]=Sum(qt[j].l); j++; } } for(i=1;i<=q;i++) printf("%I64d\n",ans[i]); } return 0; }