【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\n",arr[res[i]]);
    }
}

猜你喜欢

转载自www.cnblogs.com/tudouuuuu/p/11924776.html