HDU 3333 Turing Tree【树状数组+hash+离线】

题意: 知道了一段序列的值,有m 个询问,输出询问区间内不同数字的和。

分析:可以用离线的方法记录所有的询问,并按每个询问右区间的值排序,然后逐个插入数值,如果某个数值之前出现过,就将之前那个位置上的那个

         数删除,并在新的位置上插入数值,如果当前插入数值的序号等于某个询问的右区间,就统计该询问区间的不同数值的值,由于数值比较大,需

         要进行离散化,离散化可以用 hash 或 二分,将每个值映射到一个较小的数值上,以便用数组标记。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define maxn 30003
#define clr(x)memset(x,0,sizeof(x))
int n;
int lowbit(int x)
{
    return (x)&(-x);
}
__int64 a[maxn];
void add(int pos,__int64 x)
{
    while(pos<=n)
    {
        a[pos]+=x;
        pos+=lowbit(pos);
    }
}
__int64 getsum(int pos)
{
    if(pos==0)
        return 0;
    __int64 sum=0;
    while(pos>0)
    {
        sum+=a[pos];
        pos-=lowbit(pos);
    }
    return sum;
}
struct node
{
    __int64 key;
    int num;
}Hash[maxn<<2];
int hash_val(__int64 x)
{
    int k=x%maxn;
    while(Hash[k].num)
    {
        if(Hash[k].key==x)
            break;
        k=(k+1)%maxn;
    }
    if(Hash[k].num==0)
    {
        Hash[k].key=x;
        Hash[k].num++;
    }
    return k;
}
struct query
{
    int l,r,id;
}q[100005];
bool cmp(query a,query b)
{
    return a.r<b.r;
}
__int64 v[maxn];
__int64 res[100005];
int num[maxn];
int main()
{
    int i,t,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%I64d",&v[i]);
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        sort(q,q+m,cmp);
        clr(Hash);
        clr(a);
        clr(num);
        int j=0;
        for(i=1;i<=n;i++)
        {
            int xu=hash_val(v[i]);
            int nx=num[xu];
            if(nx)
                add(nx,-v[i]);
            add(i,v[i]);
            num[xu]=i;
            for(;j<m;j++)
            {
                if(q[j].r==i)
                    res[q[j].id]=getsum(q[j].r)-getsum(q[j].l-1);
                else break;
            }
        }
        for(i=0;i<m;i++)
            printf("%I64d\n",res[i]);
    }
    return 0;
}

 

posted @ 2012-09-12 18:13  'wind  阅读(177)  评论(0编辑  收藏  举报