zoukankan      html  css  js  c++  java
  • HDU5919 Sequence II(主席树)

    Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,,ana1,a2,⋯,anThere are m queries. 

    In the i-th query, you are given two integers lili and riri. Consider the subsequence ali,ali+1,ali+2,,ariali,ali+1,ali+2,⋯,ari. 

    We can denote the positions(the positions according to the original sequence) where an integer appears first in this subsequence as p(i)1,p(i)2,,p(i)kip1(i),p2(i),⋯,pki(i) (in ascending order, i.e.,p(i)1<p(i)2<<p(i)kip1(i)<p2(i)<⋯<pki(i)). 

    Note that kiki is the number of different integers in this subsequence. You should output p(i)ki2p⌈ki2⌉(i)for the i-th query.

    InputIn the first line of input, there is an integer T (T2T≤2) denoting the number of test cases. 

    Each test case starts with two integers n (n2×105n≤2×105) and m (m2×105m≤2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,,an,0ai2×105a1,a2,⋯,an,0≤ai≤2×105). 

    There are two integers lili and riri in the following m lines. 

    However, Mr. Frog thought that this problem was too young too simple so he became angry. He modified each query to li,ri(1lin,1rin)li‘,ri‘(1≤li‘≤n,1≤ri‘≤n). As a result, the problem became more exciting. 

    We can denote the answers as ans1,ans2,,ansmans1,ans2,⋯,ansm. Note that for each test case ans0=0ans0=0. 

    You can get the correct input li,rili,ri from what you read (we denote them as li,rili‘,ri‘)by the following formula: 

    li=min{(li+ansi1) mod n+1,(ri+ansi1) mod n+1}li=min{(li‘+ansi−1) mod n+1,(ri‘+ansi−1) mod n+1}


    ri=max{(li+ansi1) mod n+1,(ri+ansi1) mod n+1}ri=max{(li‘+ansi−1) mod n+1,(ri‘+ansi−1) mod n+1}

    OutputYou should output one single line for each test case. 

    For each test case, output one line “Case #x: p1,p2,,pmp1,p2,⋯,pm”, where x is the case number (starting from 1) and p1,p2,,pmp1,p2,⋯,pm is the answer.Sample Input

    2
    5 2
    3 3 1 5 4
    2 2
    4 4
    5 2
    2 5 2 1 2
    2 3
    2 4

    Sample Output

    Case #1: 3 3
    Case #2: 3 1
    
    
            
     

    Hint

    题解:

    题目意思是:给你n个数,然后m组询问(强制在线),每组询问L,R。

    让你求L到R区间内的去重后的中位数所在的位置。

    思路:考虑使用主席树来倒着将数组里面的数字插入主席树,每次插入一个数字a[i],在该树的位置 i 加一,然后判断其是否前面出现过,如果出现过,则在前一棵树的pre[a[i]]的位置减一;

    然后只要查询root[L]的L到R区间得和就是L到R区间的数字的种类,然后再去查找root[L]中的第K小的数字在那个位置即可。

    参考代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mkp make_pair
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;    
    }
    const int maxn=2e5+10;
    int T,n,m,cnt,a[maxn],rt[maxn],pre[maxn],ans[maxn];
    struct Node{
        int ls,rs;
        int sum;
    } tr[maxn*40];
    
    void update(int &x,int y,int l,int r,int pos,int val)
    {
        tr[++cnt]=tr[y];tr[cnt].sum+=val;x=cnt;
        if(l==r) return ;
        int mid=l+r>>1;
        if(pos<=mid) update(tr[x].ls,tr[y].ls,l,mid,pos,val);
        else update(tr[x].rs,tr[y].rs,mid+1,r,pos,val);        
    }
    int Query(int t,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R) return tr[t].sum;
        int mid=l+r>>1,ret=0;
        if(L<=mid) ret+=Query(tr[t].ls,l,mid,L,R);
        if(R>mid) ret+=Query(tr[t].rs,mid+1,r,L,R);    
        return ret;
    }
    
    int GetKth(int t,int l,int r,int k)
    {
        if(l==r) return l;
        int mid=l+r>>1,num=tr[tr[t].ls].sum;
        if(k<=num) return GetKth(tr[t].ls,l,mid,k);
        else return GetKth(tr[t].rs,mid+1,r,k-num);    
    }
    
    int main()
    {
        T=read();
        for(int cas=1;cas<=T;++cas)
        {
            memset(pre,0,sizeof(pre));
            memset(rt,0,sizeof(rt));
            n=read();m=read(); cnt=0;
            for(int i=1;i<=n;++i) a[i]=read();
            int L,R; ans[0]=0;
            
            for(int i=n;i>=1;--i)
            {
                if(!pre[a[i]]) update(rt[i],rt[i+1],1,n,i,1),pre[a[i]]=i; 
                else 
                {
                    update(rt[i],rt[i+1],1,n,i,1);
                    update(rt[i],rt[i],1,n,pre[a[i]],-1);    
                    pre[a[i]]=i;
                }
            }
            for(int i=1;i<=m;++i)
            {
                L=read();R=read();
                L=((L+ans[i-1])%n)+1;
                R=((R+ans[i-1])%n)+1;
                if(L>R) swap(L,R);
                int num=Query(rt[L],1,n,L,R)+1>>1;
                ans[i]=GetKth(rt[L],1,n,num);
            }
            printf("Case #%d:",cas);
            for(int i=1;i<m;++i) printf(" %d",ans[i]);
            printf(" %d
    ",ans[m]);    
        }
    
        return 0;    
    }
    View Code
  • 相关阅读:
    错误C2665: “AfxMessageBox”: 2 个重载中没有一个可以转换所有参数类型
    为什么DW的可视化下看到的效果与浏览器的效果有所区别?
    font-family:黑体;导致css定义全部不起作用
    web标准中定义id与class有什么区别吗
    网页尺寸规范
    SEO为什么要求网页设计师用DIV+CSS布局网页?
    去掉CSS赘余代码,CSS可以更简洁
    解决IE6、IE7、Firefox兼容最简单的CSS Hack
    实战中总结出来的CSS常见问题及解决办法
    高效整洁CSS代码原则 (下)
  • 原文地址:https://www.cnblogs.com/csushl/p/11247267.html
Copyright © 2011-2022 走看看