• D2. Optimal Subsequences (Hard Version)(贪心+主席树)


    题目链接:https://codeforces.com/contest/1262/problem/D2

    D2. Optimal Subsequences (Hard Version)
    time limit per test
    3 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    This is the harder version of the problem. In this version, 1n,m21051≤n,m≤2⋅105. You can hack this problem if you locked it. But you can hack the previous problem only if you locked both problems.

    You are given a sequence of integers a=[a1,a2,,an]a=[a1,a2,…,an] of length nn. Its subsequence is obtained by removing zero or more elements from the sequence aa (they do not necessarily go consecutively). For example, for the sequence a=[11,20,11,33,11,20,11]a=[11,20,11,33,11,20,11]:

    • [11,20,11,33,11,20,11][11,20,11,33,11,20,11], [11,20,11,33,11,20][11,20,11,33,11,20], [11,11,11,11][11,11,11,11], [20][20], [33,20][33,20] are subsequences (these are just some of the long list);
    • [40][40], [33,33][33,33], [33,20,20][33,20,20], [20,20,11,11][20,20,11,11] are not subsequences.

    Suppose that an additional non-negative integer kk (1kn1≤k≤n) is given, then the subsequence is called optimal if:

    • it has a length of kk and the sum of its elements is the maximum possible among all subsequences of length kk;
    • and among all subsequences of length kk that satisfy the previous item, it is lexicographically minimal.

    Recall that the sequence b=[b1,b2,,bk]b=[b1,b2,…,bk] is lexicographically smaller than the sequence c=[c1,c2,,ck]c=[c1,c2,…,ck] if the first element (from the left) in which they differ less in the sequence bb than in cc. Formally: there exists tt (1tk1≤t≤k) such that b1=c1b1=c1, b2=c2b2=c2, ..., bt1=ct1bt−1=ct−1 and at the same time bt<ctbt<ct. For example:

    • [10,20,20][10,20,20] lexicographically less than [10,21,1][10,21,1],
    • [7,99,99][7,99,99] is lexicographically less than [10,21,1][10,21,1],
    • [10,21,0][10,21,0] is lexicographically less than [10,21,1][10,21,1].

    You are given a sequence of a=[a1,a2,,an]a=[a1,a2,…,an] and mm requests, each consisting of two numbers kjkj and posjposj (1kn1≤k≤n, 1posjkj1≤posj≤kj). For each query, print the value that is in the index posjposj of the optimal subsequence of the given sequence aa for k=kjk=kj.

    For example, if n=4n=4, a=[10,20,30,20]a=[10,20,30,20], kj=2kj=2, then the optimal subsequence is [20,30][20,30] — it is the minimum lexicographically among all subsequences of length 22 with the maximum total sum of items. Thus, the answer to the request kj=2kj=2, posj=1posj=1 is the number 2020, and the answer to the request kj=2kj=2, posj=2posj=2 is the number 3030.

    Input

    The first line contains an integer nn (1n21051≤n≤2⋅105) — the length of the sequence aa.

    The second line contains elements of the sequence aa: integer numbers a1,a2,,ana1,a2,…,an (1ai1091≤ai≤109).

    The third line contains an integer mm (1m21051≤m≤2⋅105) — the number of requests.

    The following mm lines contain pairs of integers kjkj and posjposj (1kn1≤k≤n, 1posjkj1≤posj≤kj) — the requests.

    Output

    Print mm integers r1,r2,,rmr1,r2,…,rm (1rj1091≤rj≤109) one per line: answers to the requests in the order they appear in the input. The value of rjrj should be equal to the value contained in the position posjposj of the optimal subsequence for k=kjk=kj.

    Examples
    input
    Copy
    3
    10 20 10
    6
    1 1
    2 1
    2 2
    3 1
    3 2
    3 3
    
    output
    Copy
    20
    10
    20
    10
    20
    10
    
    input
    Copy
    7
    1 2 1 3 1 2 1
    9
    2 1
    2 2
    3 1
    3 2
    3 3
    1 1
    7 1
    7 7
    7 4
    
    output
    Copy
    2
    3
    2
    3
    2
    3
    1
    1
    3
    
    Note

    In the first example, for a=[10,20,10]a=[10,20,10] the optimal subsequences are:

    • for k=1k=1: [20][20],
    • for k=2k=2: [10,20][10,20],
    • for k=3k=3: [10,20,10][10,20,10].

     题目大意:输入N 接下来是N个数  输入M M次询问

    每次询问包括 K pos 两个数  要你从N个数中找出K个数,使得他们的总和最大,如果有多个,找出的是字典序最小的序列,并且输出找出的序列中第pos个数的值

    思路:这是一个比较难的版本,打比赛的时候超时了,只过了一个简单的版本,当时超时的原因是找出第pos个数时用了一次排序,傻逼了,这样很明显的超时

    M * Nlog(N) 这不超时怎么可能。  我们超时的原因就是求第pos个数时的复杂度太大了,打比赛的时间不够是一个原因,但是对主席树不敏感是真的,不然这个一下就会想

    的到这不是主席树求区间第K大的板子吗!! 补题想了一下才想到用主席树维护,是的 ,用主席树维护,求区间第K大就行了!

    看代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    using namespace std;
    typedef long long LL;
    const int maxn=2e5+5;
    const int maxm=100000+10;
    vector<LL>v;
    LL b[maxn];
    LL ans[maxn];
    LL root[maxn];
    LL cnt;
    int mp[maxn];//mp[i]代表第i次询问对应哪棵树
    struct Node
    {
        LL v,id;
    }a[maxn];
    struct Q
    {
        LL K,pos,id;
    }q[maxn];
    struct Tree
    {
        LL l,r,sum;//左右儿子  多少个数
    }T[maxn<<5];
    bool cmp(const Node x,const Node y)
    {
        if(x.v==y.v) return x.id<y.id;
        return x.v>y.v;
    }
    bool cmp1(const Q x,const Q y)
    {
        return x.K<y.K;
    }
    void Init()
    {
        cnt=0;T[cnt].l=T[cnt].r=T[cnt].sum=0;
        root[cnt]=0;
    }
    void Update(LL l,LL r,LL &x,LL y,LL pos)
    {
        T[++cnt]=T[y],T[cnt].sum++,x=cnt;
        if(l==r) return ;
        LL mid=(l+r)>>1;
        if(pos<=mid) Update(l,mid,T[x].l,T[y].l,pos);
        else Update(mid+1,r,T[x].r,T[y].r,pos);
    }
    LL Query(LL l,LL r,LL x,LL y,LL k)
    {
        if(l==r) return l;
        LL mid=(l+r)>>1;
        LL sum=T[T[y].l].sum-T[T[x].l].sum;
        if(sum>=k) return Query(l,mid,T[x].l,T[y].l,k);
        else return Query(mid+1,r,T[x].r,T[y].r,k-sum);
    }
    int main()
    {
        Init();//主席树初始化
        LL N;scanf("%lld",&N);
        for(int i=1;i<=N;i++)
        {
            scanf("%lld",&a[i].v);
            b[i]=a[i].v;//对应原数组
            a[i].id=i;
        }
        sort(a+1,a+N+1,cmp);//贪心 按照值从大到小排序 相等按照再前面的排序
        LL M;scanf("%lld",&M);
        for(int i=1;i<=M;i++)
        {
            scanf("%lld%lld",&q[i].K,&q[i].pos);
            q[i].id=i;
        }
        sort(q+1,q+M+1,cmp1);//贪心 按照K值从小往大排序 这样保证我们只需要走一遍数组就行
        int p=1;
        for(int i=1;i<=M;i++)//遍历每一个询问
        {
            if(q[i].K<p)//会可能出现K相等的情况 这棵树和前一颗树相等就行了 
            {
                mp[i]=mp[i-1];
                continue;
            }
            for(int j=p;j<=q[i].K;j++)//K是递增的
            {
                Update((LL)1,N,root[j],root[j-1],a[j].id);//
            }
            mp[i]=root[q[i].K];//
            p=q[i].K+1;
        }
        for(int i=1;i<=M;i++) ans[q[i].id]=b[Query(1,N,root[0],mp[i],q[i].pos)];
        for(int i=1;i<=M;i++) printf("%lld
    ",ans[i]);
        return 0;
    }
    /**
    7
    1 2 1 3 1 2 1
    3
    7 1
    7 7
    7 4
    */
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    cocos2d学习笔录1
    js 动态切换视频
    Android之一个简单计算器源代码
    git-daemon的快捷搭建
    题目1384:二维数组中的查找
    [cocos2d-x]HelloWorldDemo
    ios开发者创建app应用开发授权文件 实战方法:
    一些小工具方法,能将容器转换成指定的数组类型有使用泛型
    Mockito文档-单元测试技术
    【UNIX网络编程】FIFO
  • 原文地址:https://www.cnblogs.com/caijiaming/p/11927316.html
Copyright © 2020-2023  润新知