zoukankan      html  css  js  c++  java
  • 【CFRound#602-D2】Optimal Subsequences (Hard Version) 离线操作+Treap

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

    Descript

    This is the harder version of the problem. In this version, 1≤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] of length n. Its subsequence is obtained by removing zero or more elements from the sequence a (they do not necessarily go consecutively). For example, for the sequence a=[11,20,11,33,11,20,11]:

    [11,20,11,33,11,20,11], [11,20,11,33,11,20], [11,11,11,11], [20], [33,20] are subsequences (these are just some of the long list);
    [40], [33,33], [33,20,20], [20,20,11,11] are not subsequences.
    Suppose that an additional non-negative integer k (1≤k≤n) is given, then the subsequence is called optimal if:

    it has a length of k and the sum of its elements is the maximum possible among all subsequences of length k;
    and among all subsequences of length k that satisfy the previous item, it is lexicographically minimal.
    Recall that the sequence b=[b1,b2,…,bk] is lexicographically smaller than the sequence c=[c1,c2,…,ck] if the first element (from the left) in which they differ less in the sequence b than in c. Formally: there exists t (1≤t≤k) such that b1=c1, b2=c2, ..., bt−1=ct−1 and at the same time bt<ct. For example:

    [10,20,20] lexicographically less than [10,21,1],
    [7,99,99] is lexicographically less than [10,21,1],
    [10,21,0] is lexicographically less than [10,21,1].
    You are given a sequence of a=[a1,a2,…,an] and m requests, each consisting of two numbers kj and posj (1≤k≤n, 1≤posj≤kj). For each query, print the value that is in the index posj of the optimal subsequence of the given sequence a for k=kj.

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

    Input

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

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

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

    The following m lines contain pairs of integers kj and posj (1≤k≤n, 1≤posj≤kj) — the requests.

    Output

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

    思路

    D1已经用了暴力,显然这道题不能暴力。
    先sort一遍,保证和最大,并且在对值相同的元素,优先插入顺序小的。
    多次查询,离线操作,用Treap维护区间第k小。
    感谢洛谷用户天上一颗蛋提供的Treap模板。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int SIZE = 2e5+5;
    
    //----------------------模板Begin--------------------
    #define inf 0x3f3f3f3f
    const int maxn = 2e6+5;
    int ch[maxn][2];
    int val[maxn],dat[maxn];
    int sz[maxn],cnt[maxn];
    int tot,root;
    int New(int v){// 辅助函数
        val[++tot] = v;
        dat[tot] = rand();
        sz[tot] = 1;
        cnt[tot] = 1;
        return tot;
    }
    void pushup(int id){// 辅助函数
        sz[id] = sz[ch[id][0]] + sz[ch[id][1]] + cnt[id];
    }
    void build(){// 辅助函数
        root = New(-inf),ch[root][1] = New(inf);
        pushup(root);
    }
    void Rotate(int &id,int d){// 辅助函数
        int temp = ch[id][d ^ 1];
        ch[id][d ^ 1] = ch[temp][d];
        ch[temp][d] = id;
        id = temp;
        pushup(ch[id][d]),pushup(id);
    }
    void insert(int &id,int v){// 插入一个数值为v
    if(!id){
        id = New(v);return ;
    }
    if(v == val[id])cnt[id]++;
    else{
        int d = v < val[id] ? 0 : 1;
        insert(ch[id][d],v);
        if(dat[id] < dat[ch[id][d]])Rotate(id,d ^ 1);
    }
    pushup(id);
    }
    
    int get_val(int id,int rank){// 查询排名为rank的数
        if(!id)return inf;
        if(rank <= sz[ch[id][0]])return get_val(ch[id][0],rank);
            else if(rank <= sz[ch[id][0]] + cnt[id])return val[id];
        else return get_val(ch[id][1],rank - sz[ch[id][0]] - cnt[id]);
    }
    //-----------------------模板End-----------------------
    
    struct node{
        int num,id;
        bool operator <(const node& b)const{
            if(num==b.num)return id<b.id;
            return num>b.num;
        }
    }p[SIZE];
    int arr[SIZE];
    struct qwq{
        int k,pos,id;
        bool operator <(const qwq& b)const{
            return k<b.k;
        }
    }q[SIZE];
    int res[SIZE];
    
    int main(){
        
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&p[i].num);
            arr[i]=p[i].num;
            p[i].id = i;
        }
        sort(p+1,p+1+n);
        int qq;scanf("%d",&qq);
        for(int i=1;i<=qq;i++){
            scanf("%d%d",&q[i].k,&q[i].pos);
            q[i].id = i;
        }
        sort(q+1,q+qq+1);//比赛的时候把qq写成了n,手滑害人,我还以为板子错了qwq
        int pos = 1;
        build();
        for(int i=1;i<=qq;i++){
            for(int j=pos;j<=q[i].k;j++){
                insert(root,p[j].id);
            }
            pos = q[i].k+1;
            res[q[i].id] = get_val(root,q[i].pos+1);
        }
        for(int i=1;i<=qq;i++){
            printf("%d
    ",arr[res[i]]);
        }
    }
    
  • 相关阅读:
    element ui 时间控件 多个日期
    java 获取两个日期之间的所有日期(年月日)
    java 正则表达式(内附例子)
    Notepad++怎么使用正则替换
    基于 vue+element ui 的cdn网站(多页面,都是各种demo)
    使用github搭建个人html网站
    PL/SQL Developer 如何记住密码
    PL/SQL Developer图形化窗口创建数据库(表空间和用户)以及相关查询sql
    安装pl/sql developer(内附下载地址)
    vue中操作cookie的插件
  • 原文地址:https://www.cnblogs.com/tudouuuuu/p/11924776.html
Copyright © 2011-2022 走看看