HDU-5919 Sequence II 主席树二分

来源:互联网 发布:php框架类库有哪些 编辑:程序博客网 时间:2024/06/05 05:12

Sequence II

题意:给你n个数,q次查询,每次查询一个区间,求这个区间的不同数的最中间的那个的第一次出现的位置。

主席树裸题吧。查询区间不同数的个数模板然后嵌套个二分,二分答案mid,判断[l,mid]之间不同数的个数是否大于等于(k+1)/2,是则更新右端点,反之更新左端点,注意强制在线的左端点不能变,另外用一个变量表示左端点,每次更新它即可。 

const int N=2e5+10;inline int sc(){    char ch=getchar();    int sum=0;    while(!(ch>='0'&&ch<='9'))ch=getchar();    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=getchar();    return sum;}int n,q,tot;int a[N],T[N],lc[N*50],rc[N*50],c[N*50];int ans[N];int build(int l,int r){    int root=tot++;    c[root]=0;    if(l!=r)    {        int mid=(l+r)>>1;        lc[root]=build(l,mid);        rc[root]=build(mid+1,r);    }    return root;}int update(int root,int pos,int val){    int newroot=tot++,tmp=newroot;    c[newroot]=c[root]+val;    int l=1,r=n;    while(l<r)    {        int mid=(l+r)>>1;        if(pos<=mid)        {            lc[newroot]=tot++;            rc[newroot]=rc[root];            newroot=lc[newroot];            root=lc[root];            r=mid;        }        else        {            rc[newroot]=tot++;            lc[newroot]=lc[root];            newroot=rc[newroot];            root=rc[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=lc[root];        }        else        {            ret+=c[lc[root]];            root=rc[root];            l=mid+1;        }    }    return ret+c[root];}map<int,int>mp;int main(){    int t;    scanf("%d",&t);    int t1=t;    while(t--)    {        tot=0;        scanf("%d%d",&n,&q);        for(int i=1; i<=n; i++) a[i]=sc();        T[n+1]=build(1,n);        mp.clear();        for(int i=n; i>=1; i--)        {            if(mp.find(a[i])==mp.end()) T[i]=update(T[i+1],i,1);            else            {                int tmp=update(T[i+1],mp[a[i]],-1);                T[i]=update(tmp,i,1);            }            mp[a[i]]=i;        }        int l,r;        ans[0]=0;        for(int i=1; i<=q; i++)        {            l=sc();            r=sc();            int l1,r1;            l1=min((l+ans[i-1])%n+1,(r+ans[i-1])%n+1);            r1=max((l+ans[i-1])%n+1,(r+ans[i-1])%n+1);            l=l1,r=r1;            int k=(1+query(T[l1],r1))/2;            while(l1<=r1)            {                int mid=(l1+r1)>>1;                if(query(T[l],mid)>=k) ans[i]=mid,r1=mid-1;                else l1=mid+1;            }        }        printf("Case #%d: ",t1-t);        for(int i=1; i<=q; i++) printf("%d%c",ans[i],i==q?'\n':' ');    }    return 0;}


原创粉丝点击