SPOJ DQUERY (主席樹求區間不同數個數)


題意:找n個數中無修改的區間不同數個數

 

題解:使用主席樹在線做,我們不能使用權值線段樹建主席樹

我們需要這么想:從左向右添加一到主席樹上,添加的是該數字處在的位置

但是如果該數字前面出現過,就在此版本的主席樹上的前面出現的位置減一,接着才在此位置上添一

這樣查找是按照右區間版本的主席樹來找(lef,rig)的數字

因為要將此區間每個不同的數都處在最后出現的位置

 

/*在線求區間內不同的數的個數:從頭到尾添加到線段樹(不是權值線段樹,是存值的線段樹)中
如果此數之前出現過就先減去,接着再加,最后在區間(l,r)中找到root[r]這個歷史版本*/
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define dir(a,b) (a>>b)
const int Max=30010;
int root[Max],tot,val[Max];
struct node
{
    int lef,rig,sum;
}msegtr[Max*40];
map<int,int> mp;
void Init()
{
    tot=0;
    msegtr[0].lef=msegtr[0].rig=msegtr[0].sum=0;
    root[0]=0;
    mp.clear();
    return;
}
void Create(int sta,int enn,int &x,int y,int pos,int aad)
{
    msegtr[++tot]=msegtr[y];
    msegtr[tot].sum+=aad;
    x=tot;
    if(sta==enn)
        return;
    int mid=dir(sta+enn,1);
    if(mid>=pos)
        Create(sta,mid,msegtr[x].lef,msegtr[y].lef,pos,aad);
    else
    Create(mid+1,enn,msegtr[x].rig,msegtr[y].rig,pos,aad);
    return;
}
int Query(int sta,int enn,int x,int y)//只有左邊有界限
{
    if(sta>=y)
        return msegtr[x].sum;
    int mid=dir(sta+enn,1);
    if(mid>=y)
        return Query(sta,mid,msegtr[x].lef,y)+msegtr[msegtr[x].rig].sum;
    else
        return Query(mid+1,enn,msegtr[x].rig,y);
}
int main()
{
    int n,m,temp;
    int lef,rig;
    while(~scanf("%d",&n))
    {
         Init();
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&val[i]);
        if(!mp.count(val[i]))//直接加
        {
            Create(1,n,root[i],root[i-1],i,1);//注意是在i這個位置加1,不是權值線段樹的val[i]位置加1
        }
        else
        {
            Create(1,n,temp,root[i-1],mp[val[i]],-1);//先在原位置減去1
            Create(1,n,root[i],temp,i,1);
        }
        mp[val[i]]=i;
    }
    scanf("%d",&m);
    for(int i=0;i<m;++i)
    {
        scanf("%d %d",&lef,&rig);
        printf("%d\n",Query(1,n,root[rig],lef));//在rig的歷史版本上找(lef,rig)的值
    }
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM