A - Sequence II

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919

题意: 给一个区间,经过运算后会得到一个区间。然后问这个区间里面有几个个不同的数,假设不同的数有n个,

            然后将这个区间不同的数进行排序,输出第n/2个的在区间第一次出现的下标就可以了。

思路:我这是主席树专题里的,肯定要往主席树想,题目要的是第一次出现的位置,所以可以从后往前建树。

          然后按照每个位置的下标进行维护,再来个数组避免重复就可以了,数组记得要开大点

#include<iostream>
#include<cmath>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
int a[8000010];
int root[2000010],lson[8000010],rson[8000010];
int sum[8000010],top,fa[2000010];
void init()
{
    top = 0;
    memset(sum,0,sizeof(sum));
    memset(root,0,sizeof(root));
    memset(lson,0,sizeof(lson));
    memset(rson,0,sizeof(rson));
    for(int i=0;i<2000010;i++)
        fa[i]=-1;
}
void Update(int l,int r,int &now,int last,int pos,int x)
{
    now=++top;
    lson[now]=lson[last];
    rson[now]=rson[last];
    sum[now]=sum[last]+x;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    if(pos<=mid)
        Update(l,mid,lson[now],lson[last],pos,x);
    else
        Update(mid+1,r,rson[now],rson[last],pos,x);
}

int Query(int rt,int L,int R,int l,int r)
{
    if(l<=L&&r>=R)
        return sum[rt];
    int mid=(L+R)>>1;
    int ans=0;
    if(l<=mid)
        ans+=Query(lson[rt],L,mid,l,r);
    if(r>mid)
        ans+=Query(rson[rt],mid+1,R,l,r);
    return ans;
}
int getpos(int rt,int l,int r,int k)
{
    if(l==r)
        return l;
    int ans=sum[lson[rt]];
    int mid=(l+r)>>1;
    if(ans>=k)
        return getpos(lson[rt],l,mid,k);
    else
        return getpos(rson[rt],mid+1,r,k-ans);
}
int main()
{
    int T,n,m;
    scanf("%d",&T);
    int u=0;
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=n;i>=1;i--)
        {
            if(fa[a[i]]==-1)
                Update(1,n,root[i],root[i+1],i,1);
            else
            {
                Update(1,n,root[i],root[i+1],fa[a[i]],-1);
                Update(1,n,root[i],root[i],i,1);
            }
            fa[a[i]] = i;
        }
        int ans = 0;
        printf("Case #%d:",++u);
        while(m--)
        {
            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 k=(Query(root[l],1,n,l,r)+1)>>1;
            printf(" %d",ans=getpos(root[l],1,n,k));
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2019-11-27 01:22  ~zcb  阅读(106)  评论(0编辑  收藏  举报