CodeForces 1277D Optimal Subsequences(主席树or贪心+线段树)

Description

\quad You are given a sequence of integers a = [ a 1 , a 2 . . . a n ] a=[a_{1},a_{2}...a_{n}] a=[a1,a2...an] of length n n 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 ] 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 , 11 , 11 ] , [ 20 ] [11,20,11,33,11,20,11], [11,20,11,33,11,20], [11,11,11,11], [20] [11,20,11,33,11,20,11],[11,20,11,33,11,20],[11,11,11,11],[20]
    [ 33 , 20 ] [33,20] [33,20] are subsequences (these are just some of the long list);
  • [ 40 ] , [ 33 , 33 ] , [ 33 , 20 , 20 ] , [ 20 , 20 , 11 , 11 ] [40], [33,33], [33,20,20], [20,20,11,11] [40],[33,33],[33,20,20],[20,20,11,11] are not subsequences.

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

\quad it has a length of k k k and the sum of its elements is the maximum possible among all subsequences of length k k k;
and among all subsequences of length k k k that satisfy the previous item, it is lexicographically minimal.
Recall that the sequence b = [ b 1 , b 2 . . . b k ] b=[b_{1},b_{2}...b_{k}] b=[b1,b2...bk] is lexicographically smaller than the sequence c = [ c 1 , c 2 . . . c k ] c=[c_{1},c_{2}...c_{k}] 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 b 1 = c 1 , b 2 = c 2 . . . . b t − 1 = c t − 1 b_{1}=c_{1},b_{2}=c_{2}....b_{t-1}=c_{t-1} b1=c1b2=c2....bt1=ct1 and at the same time b t < c t b_{t}<c_{t} bt<ct. For example:

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

\quad You are given a sequence of a = [ a 1 , a 2 . . . a n ] a=[a_{1},a_{2}...a_{n}] a=[a1,a2...an] and m requests, each consisting of two numbers k j k_{j} kj and p o s j pos_{j} posj ( 1 ≤ k ≤ n , 1 ≤ p o s j ≤ k j ) (1≤k≤n, 1≤pos_{j}≤k_{j}) (1kn,1posjkj). For each query, print the value that is in the index posj of the optimal subsequence of the given sequence a for k = k j k=k_{j} k=kj.

\quad For example, if n = 4 n=4 n=4, a = [ a 1 , a 2 . . . a n ] a=\left[a_{1},a_{2}...a_{n}\right] a=[a1,a2...an], k j = 2 k_{j}=2 kj=2, then the optimal subsequence is [ 20 , 30 ] [20,30] [20,30] — it is the minimum lexicographically among all subsequences of length 2 2 2 with the maximum total sum of items. Thus, the answer to the request k j = 2 k_{j}=2 kj=2, p o s j = 1 pos_{j}=1 posj=1 is the number 20 20 20, and the answer to the request k j = 2 k_{j}=2 kj=2, p o s j = 2 pos_{j}=2 posj=2 is the number 30 30 30.

Input

\quad The first line contains an integer n ( 1 ≤ n ≤ 2 ∗ 1 0 5 ) n\left(1≤n≤2*10^{5} \right) n(1n2105) — the length of the sequence a a a.

\quad The second line contains elements of the sequence a: integer numbers a 1 , a 2 . . . a n ( 1 ≤ a i ≤ 1 0 9 ) a_{1},a_{2}...a_{n}\left(1≤a_{i}≤10^{9} \right) a1,a2...an(1ai109)

\quad The third line contains an integer m ( 1 ≤ m ≤ 2 ∗ 1 0 5 ) m\left(1≤m≤2*10^{5} \right) m(1m2105) — the number of requests.

\quad The following m lines contain pairs of integers k j k_{j} kj and p o s j pos_{j} posj ( 1 ≤ k ≤ n , 1 ≤ p o s j ≤ k j ) (1≤k≤n, 1≤pos_{j}≤k_{j}) (1kn,1posjkj) — the requests.

Output

\quad Print m integers r 1 , r 2 . . . r n ( 1 ≤ r i ≤ 1 0 9 ) r_{1},r_{2}...r_{n}\left(1≤r_{i}≤10^{9} \right) r1,r2...rn(1ri109) one per line: answers to the requests in the order they appear in the input. The value of r j r_{j} rj should be equal to the value contained in the position posj of the optimal subsequence for k = k j k=k_{j} k=kj.

Examples

input

3
10 20 10
6
1 1
2 1
2 2
3 1
3 2
3 3

output

20
10
20
10
20
10

input

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

2
3
2
3
2
3
1
1
3

Note

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

  • for k=1: [20],
  • for k=2: [10,20],
  • for k=3: [10,20,10].
    这道题的题意就是:给你一个序列,让你找一个长度为K的区间(可以不连续),这个区间的和最大,然后询问你这个区间第pos的数字是哪一个。
    这个问题不就是区间第K大的问题吗,标准的主席树模板。

AC代码:

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define pd(n) printf("%d\n", n)
#define pc(n) printf("%c", n)
#define pdd(n,m) printf("%d %d", n, m)
#define pld(n) printf("%lld\n", n)
#define pldd(n,m) printf("%lld %lld\n", n, m)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sc(n) scanf("%c",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define mem(a,n) memset(a, n, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mod(x) ((x)%MOD)
#define gcd(a,b) __gcd(a,b)
#define lowbit(x) (x&-x)
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const int maxn = 3e5 + 5;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
inline int read()
{
    int ret = 0, sgn = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
            sgn = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        ret = ret*10 + ch - '0';
        ch = getchar();
    }
    return ret*sgn;
}
inline void Out(int a)    //Êä³öÍâ¹Ò
{
    if(a>9)
        Out(a/10);
    putchar(a%10+'0');
}

int qpow(int m, int k, int mod)
{
    int res = 1, t = m;
    while (k)
    {
        if (k&1)
            res = res * t % mod;
        t = t * t % mod;
        k >>= 1;
    }
    return res;
}

ll gcd(ll a,ll b)
{
    return b==0?a : gcd(b,a%b);
}

ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}
const int MAX_N=2e5+5;
int a[MAX_N];
int n,m;
struct node
{
    int val,id;
} b[MAX_N];
bool cmp(node aa,node bb)
{
    if(aa.val!=bb.val)
        return aa.val>bb.val;
    else
        return aa.id<bb.id;
}
struct Node
{
    int lc,rc,sum;
} tr[MAX_N*30];
int T[MAX_N],tot;
void build(int &k,int l,int r)
{
    k=++tot;
    tr[k].sum=0;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    build(tr[k].lc,l,mid),build(tr[k].rc,mid+1,r);
}
void update(int &k,int l,int r,int pre,int x)
{
    k=++tot;
    tr[k]=tr[pre],tr[k].sum++;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    if(x<=mid)
        update(tr[k].lc,l,mid,tr[pre].lc,x);
    else
        update(tr[k].rc,mid+1,r,tr[pre].rc,x);
}
int query(int s,int e,int l,int r,int k)
{
    if(l==r)
        return l;
    int mid=(l+r)>>1;
    int lcleft=tr[tr[e].lc].sum-tr[tr[s].lc].sum;
    if(k<=lcleft)
        return query(tr[s].lc,tr[e].lc,l,mid,k);
    else
        return query(tr[s].rc,tr[e].rc,mid+1,r,k-lcleft);
}
int main()
{
    sd(n);
    rep(i,1,n)
    {
        sd(a[i]);
        b[i].val=a[i],b[i].id=i;
    }
    sort(b+1,b+1+n,cmp);
    build(T[0],1,n);
    rep(i,1,n)
    {
        update(T[i],1,n,T[i-1],b[i].id);
    }
    sd(m);
    int k,pos;
    while(m--)
    {
        sd(k);
        sd(pos);
        printf("%d\n",a[query(T[0],T[k],1,n,pos)]);
    }
    return 0;
}

不过使用贪心+线段树也可以,这个思路是真的巧妙又学会一招。
不理解的可以看这张图,线段树维护的区间出现次数。
在这里插入图片描述

AC代码:

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
using namespace std;
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define pd(n) printf("%d\n", n)
#define pc(n) printf("%c", n)
#define pdd(n,m) printf("%d %d", n, m)
#define pld(n) printf("%lld\n", n)
#define pldd(n,m) printf("%lld %lld\n", n, m)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sc(n) scanf("%c",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define mem(a,n) memset(a, n, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mod(x) ((x)%MOD)
#define gcd(a,b) __gcd(a,b)
#define lowbit(x) (x&-x)
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const int maxn = 3e5 + 5;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
inline int read()
{
    int ret = 0, sgn = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
            sgn = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        ret = ret*10 + ch - '0';
        ch = getchar();
    }
    return ret*sgn;
}
inline void Out(int a)    //Êä³öÍâ¹Ò
{
    if(a>9)
        Out(a/10);
    putchar(a%10+'0');
}

int qpow(int m, int k, int mod)
{
    int res = 1, t = m;
    while (k)
    {
        if (k&1)
            res = res * t % mod;
        t = t * t % mod;
        k >>= 1;
    }
    return res;
}

ll gcd(ll a,ll b)
{
    return b==0?a : gcd(b,a%b);
}

ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}


const int N = 2e5 + 10;
int n, m, now;
int sum[N<<2];
struct node
{
    int x,pos;
} a[N], b[N];

struct Node
{
    int k,pos,id,ans;
} q[N];

void update(int l,int r,int rt,int pos)
{
    if(pos==l&&l==r)
    {
        sum[rt]=1;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
        update(l,mid,rt<<1,pos);
    else
        update(mid+1,r,rt<<1|1,pos);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

int query(int l,int r,int rt,int k)
{
    if(l==r)
        return a[l].x;
    int mid=(l+r)>>1;
    if(sum[rt<<1]>=k)
        return query(l,mid,rt<<1,k);
    else
        return query(mid+1,r,rt<<1|1,k-sum[rt<<1]);
}

bool cmp1(node &a,node &b)
{
    return a.x==b.x?a.pos<b.pos:a.x>b.x;
}

bool cmp2(Node &a,Node &b)
{
    return a.k<b.k;
}

bool cmp3(Node &a,Node &b)
{
    return a.id<b.id;
}

int main()
{
    sd(n);
    now=0;
    rep(i,1,n)
    {
        sd(a[i].x);
        a[i].pos=i;
        b[i]=a[i];
    }
    sort(b+1,b+n+1,cmp1);///把元素从大到小排序,位置从小到大
    sd(m);
    rep(i,1,m)
    {
        sdd(q[i].k,q[i].pos);
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp2);///按照区间从小到大排序
    rep(i,1,m)
    {
        while(now<q[i].k)
            update(1,n,1,b[++now].pos);///从大到小把每个点更新
        q[i].ans=query(1,n,1,q[i].pos);
    }
    sort(q+1,q+m+1,cmp3);///按照查询顺序排序
    rep(i,1,m)
    cout<<q[i].ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值