• HDU 5919 Sequence II 主席树


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5919

    Sequence II

    Time Limit: 9000/4500 MS (Java/Others)
    Memory Limit: 131072/131072 K (Java/Others)
    #### 问题描述 > Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,⋯,an There are m queries. > > In the i-th query, you are given two integers li and ri. Consider the subsequence ali,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)ki (in ascending order, i.e.,p(i)1 > Note that ki is the number of different integers in this subsequence. You should output p(i)⌈ki2⌉for the i-th query. #### 输入 > In the first line of input, there is an integer T (T≤2) denoting the number of test cases. > > Each test case starts with two integers n (n≤2×105) and m (m≤2×105). There are n integers in the next line, which indicate the integers in the sequence(i.e., a1,a2,⋯,an,0≤ai≤2×105). > > There are two integers li and ri 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 l‘i,r‘i(1≤l‘i≤n,1≤r‘i≤n). As a result, the problem became more exciting. > > We can denote the answers as ans1,ans2,⋯,ansm. Note that for each test case ans0=0. > > You can get the correct input li,ri from what you read (we denote them as l‘i,r‘i)by the following formula: > li=min{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1} > > ri=max{(l‘i+ansi−1) mod n+1,(r‘i+ansi−1) mod n+1} #### 输出 > You should output one single line for each test case. > > For each test case, output one line “Case #x: p1,p2,⋯,pm”, where x is the case number (starting from 1) and p1,p2,⋯,pm is the answer. ####样例输入 > 2 > 5 2 > 3 3 1 5 4 > 2 2 > 4 4 > 5 2 > 2 5 2 1 2 > 2 3 > 2 4

    样例输出

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

    题意

    求区间[l,r]的所有不重复的数(重复的以第一次出现的位置为准)位于中间(位置在中间,不是值)那个数所在的位置。
    题目强制在线

    题解

    用主席树,倒过来建树,从第n个位置建到第1个位置,对于重复的数边做边删,保证只留在最左边的那个,然后对于查询[l,r],我们去查rt[l]那棵树的l,r区间,得到不重复的数有cnt个,然后用求区间第k大的办法去求第(cnt+1)/2大的数。

    还有一种思路,每个数存它前驱的位置,然后用主席树求区间[l,r]中比l小的数的个数,从而可以求区间[l,r]内不同的数的个数,然后二分t,去找中间的位置, 这样的复杂度是nlogn+q*logn*logn,会卡时间,反正我是t了。

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    #include<sstream>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define mid (l+(r-l)/2)
    #define lson(o) (tre[(o)].ls)
    #define rson(o) (tre[(o)].rs)
    #define sumv(o) (tre[(o)].sum)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-8;
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=201010;
    
    ///nlogn空间复杂度
    ///注意:由于有增加和删除两个操作!所以空间是2n*log(2n)
    struct Tre {
        int ls,rs,sum;
        Tre() {
            ls=rs=sum=0;
        }
    } tre[maxn*50];
    
    int n,m;
    int rt[maxn],tot;
    
    int _v,_p;
    void update(int &o,int l,int r) {
        tre[++tot]=tre[o],o=tot;
        if(l==r) {
            sumv(o)+=_v;
        } else {
            if(_p<=mid) update(lson(o),l,mid);
            else update(rson(o),mid+1,r);
            sumv(o)=sumv(lson(o))+sumv(rson(o));
        }
    }
    
    ///区间内不同的数有几个
    int _res,ql,qr;
    void query(int o,int l,int r) {
        if(ql<=l&&r<=qr) {
            _res+=sumv(o);
        } else {
            if(ql<=mid) query(lson(o),l,mid);
            if(qr>mid) query(rson(o),mid+1,r);
        }
    }
    
    ///区间第k大
    int _res2;
    void query2(int o,int l,int r,int k) {
        if(l==r) {
            _res2=l;
        } else {
            if(k<=sumv(lson(o))) query2(lson(o),l,mid,k);
            else query2(rson(o),mid+1,r,k-sumv(lson(o)));
        }
    }
    
    int arr[maxn],mp[maxn];
    
    ///0是个超级节点
    void init() {
        rt[n+1]=tot=0;
    }
    
    int main() {
        int tc,kase=0;
        scf("%d",&tc);
        while(tc--) {
            scf("%d%d",&n,&m);
            init();
            for(int i=1; i<=n; i++) {
                scf("%d",&arr[i]);
            }
    
            ///主席树
            for(int i=1; i<=n; i++) mp[i]=n+1;
            for(int i=n; i>=1; i--) {
                rt[i]=rt[i+1];
                _v=1,_p=i;
                update(rt[i],1,n);
                if(mp[arr[i]]<=n) {
                    _v=-1,_p=mp[arr[i]];
                    update(rt[i],1,n);
    
                }
                mp[arr[i]]=i;
            }
    
            int ans=0;
            VI lis;
            while(m--) {
                int ll,rr;
                scf("%d%d",&ll,&rr);
                int t1=(ll+ans)%n+1,t2=(rr+ans)%n+1;
                int l=min(t1,t2),r=max(t1,t2);
    
                ///求区间内不同的数有几个
                ql=l,qr=r,_res=0;
                query(rt[l],1,n);
                int k=(_res+1)/2;
    
    
                ///求区间第k大
                query2(rt[l],1,n,k);
    
                ans=_res2;
                lis.pb(ans);
            }
            prf("Case #%d:",++kase);
            rep(i,0,lis.sz()) {
                prf(" %d",lis[i]);
            }
            putchar('
    ');
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    Mac下MyEclipse安装及破解
    Mac系统安装和配置tomcat步骤详解
    android studio 导入主题设置,代码风格(附带eclipse 主题代码样式)
    电子书及阅读器Demo
    kettle大数据量读写mysql性能优化
    Git错误non-fast-forward后的冲突解决(转载)
    Mysql导出数据
    git 的使用(4)-git暂缓区工作区原理和修改删除等命令
    Lucene使用IKAnalyzer分词实例 及 IKAnalyzer扩展词库
    solr6安装部署
  • 原文地址:https://www.cnblogs.com/fenice/p/5933231.html
Copyright © 2020-2023  润新知