hdu3333 (线段树+离散化+离线处理)

题意是询问区间里不重复数字的和 ,采用离线处理,先对询问区间按右值排序(也可以按左值),并记录输入的顺序,然后进行更新和查询,对每一个要更新的值先判断之前有没有出现过,如果出现过就消除之前的,再更新当前的并记录位置(数据比较大,可以用到离散化), 如果当前更新的和查询的右值相同则查询。注意__int64 


#include<stdio.h>

#include<string.h>

#include<algorithm>
#include<iostream>
using namespace std;


#define LL(x) (x<<1)
#define RR(x) ((x<<1)|1)


struct node
{
    int L,R,ii;
}A[100010];
struct Node
{
    int i;
    int tt;
}B[30010];
int map[30010];
int cmp(node a,node b)
{
    return a.R<b.R;
}
int cmp1(Node a,Node b)
{
    return a.tt<b.tt;
}
int cmp2(Node a,Node b)
{
    return a.i<b.i;
}
__int64 num[4*30010];
int update(int L,int R,int pos,int mark,int k)
{
    if(k>0)num[mark]+=map[k];
    else num[mark]-=map[-k];
    if(L==R&&L==pos)
    {
        return 0;
    }    
    int mid=(L+R)/2;
    if(pos<=mid)
    {
        update(L,mid,pos,LL(mark),k);
    }
    else update(mid+1,R,pos,RR(mark),k);
    return 0;
}
__int64 find(int L,int R,int left,int right,int mark)
{
    if(L==left&&R==right)
    {
        return num[mark];
    }    
    int mid=(L+R)/2;
    if(right<=mid)
    {
        return find(L,mid,left,right,LL(mark));
    }
    else if(left>mid)
    {
        return find(mid+1,R,left,right,RR(mark));
    }
    else return find(L,mid,left,mid,LL(mark))+find(mid+1,R,mid+1,right,RR(mark));
}
int main()
{
    int T,i,j,n,m,a,b;
    int leap[30010];
    __int64 print[100010];
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&B[i].tt);
            B[i].i=i;
        }
        scanf("%d",&m);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&A[i].L,&A[i].R);
            A[i].ii=i;
        }
        memset(num,0,sizeof(num));
        sort(B+1,B+1+n,cmp1);
        sort(A+1,A+1+m,cmp);
        int k=-1;
        j=0;
        for(i=1;i<=n;i++)
        {
            if(B[i].tt!=k)
            {
                k=B[i].tt;
                j++;
                map[j]=k;
                B[i].tt=j;
            }
            else B[i].tt=j;
        }
        sort(B+1,B+1+n,cmp2);
        memset(leap,0,sizeof(leap));
        for(i=1,j=1;i<=n&&j<=m;i++)
        {   
            if(leap[B[i].tt]) update(1,n,leap[B[i].tt],1,-B[i].tt);
            update(1,n,i,1,B[i].tt);
            leap[B[i].tt]=i;
            while(i==A[j].R)
            {   
                print[A[j].ii]=find(1,n,A[j].L,A[j].R,1);
                j++;
                if(j>m) break;    
            }    
        }
        for(i=1;i<=m;i++)
        printf("%I64d\n",print[i]);
    }    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/daydream1000/article/details/78245345