首页 > 代码库 > hdu 5919 主席树入门题

hdu 5919 主席树入门题

主席树是从右往左初始化,每次把这个数出现过的位置消去,然后在当前位置加一。

然后我的做法是查两遍,第一遍能找出不同的个数,除一半;再用这个值查,一直到底,最后返回位置,比较套路的一题。

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;map<int,int>mp;const int MAXN = 200010;const int M = MAXN * 50;int n,q,tot;int a[MAXN];int rt[M],lson[M],rson[M],c[M];int build(int l,int r){    int root = tot++;//    printf ("%d---%d,%d\n",l,r,root);    c[root] = 0;    if(l != r)    {        int mid = (l+r)>>1;        lson[root] = build(l,mid);        rson[root] = build(mid+1,r);    }    return root;}int update(int root,int pos,int val){    int newroot = tot++;    int tmp = newroot;    c[newroot] = c[root] + val;    int l = 1, r = n;    while(l < r)    {        int mid = (l+r)>>1;        if(pos <= mid)        {            lson[newroot] = tot++;            rson[newroot] = rson[root];            newroot = lson[newroot];            root = lson[root];            r = mid;        }        else        {            rson[newroot] = tot++;            lson[newroot] = lson[root];            newroot = rson[newroot];            root = rson[root];            l = mid+1;        }        c[newroot] = c[root] + val;    }    return tmp;}int query(int root,int pos){    int ret = 0;    int l = 1, r = n;    while(pos < r)    {        int mid = (l+r)>>1;        if(pos <= mid)        {            r = mid;            root = lson[root];        }        else        {            ret += c[lson[root]];            root = rson[root];            l = mid+1;        }    }    return ret + c[root];}int query_pos(int root,int val){    int l = 1, r = n;    while(l<r)    {        int mid = (l+r)>>1;        if(val <= c[lson[root]])        {            r = mid;            root = lson[root];        }        else        {            val-=c[lson[root]];            root = rson[root];            l = mid+1;        }    }    return r;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int T,ncas=1;    scanf ("%d",&T);    while(T--)    {        scanf ("%d%d",&n,&q);        tot = 0;        for(int i = 1; i <= n; i++)            scanf("%d",&a[i]);        rt[n+1] = build(1,n);        mp.clear();        for(int i = n; i>= 1; i--)        {            if(mp.find(a[i]) == mp.end())            {                rt[i] = update(rt[i+1],i,1);            }            else            {                int tmp = update(rt[i+1],mp[a[i]],-1);                rt[i] = update(tmp,i,1);            }            mp[a[i]] = i;        }        int ans=0;        printf ("Case #%d:",ncas++);        while(q--)        {            int l,r;            scanf("%d%d",&l,&r);            l=(l+ans)%n+1;            r=(r+ans)%n+1;            if (l>r) swap(l,r);            int dif=query(rt[l],r);            ans=query_pos(rt[l],(dif+1)/2);            printf(" %d",ans);        }        printf ("\n");    }    return 0;}

 

hdu 5919 主席树入门题