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;

}

 

 

你可能感兴趣的:(树状数组)