codeforces 1262D1/D2 Optimal Subsequences

线段树二分第k大值

#include <bits/stdc++.h>
using namespace std;
const int maxn = 8e5 + 7;

int tree[maxn];
int l[maxn];
int r[maxn];

int a[maxn];
int b[maxn];
struct ope{
   int k, p, ind;
}q[maxn];
int n, m;
int ans[maxn];
bool cmp (int x, int y)
{
   return a[x - 1] == a[y - 1] ? x < y : a[x - 1] > a[y - 1];
}
bool cmp1 (ope &a, ope &b)
{
   return a.k == b.k ? a.p < b.p : a.k < b.k;
}
void build (int v, int ll, int rr)
{
   l[v] = ll;
   r[v] = rr;
   tree[v] = 0;
   if(ll == rr)
       return ;
   int mid = ll + rr >> 1;
   build(v * 2, ll, mid);
   build(v * 2 + 1, mid + 1, rr);
}
void add (int x, int val, int v)
{
   tree[v] += val;
   if(l[v] == r[v])
       return ;
   int mid = l[v] + r[v] >> 1;
   if(x <= mid)
   {
       add(x, val, v * 2);
   }
   else
   {
       add(x, val, v * 2 + 1);
   }
}
int query (int v, int ll, int rr)
{
   if(ll == l[v] && r[v] == rr)
   {
       return tree[v];
   }
   int mid = l[v] + r[v] >> 1;
   int res = 0;
   if(rr <= mid)
   {
       res += query(v * 2, ll, rr);
   }
   else
   {
       if(ll >= mid)
       {
           res += query(v * 2 + 1, ll, rr);
       }
       else
       {
           res += query(v * 2, ll, mid);
           res += query(v * 2 + 1, mid + 1, rr);
       }
   }
   return res;

}
int work (int val)
{
   int l = 1;
   int r = n;
   int mid;
   while(l != r)
   {
       mid = l + r >> 1;
       if(query(1, 1, mid) >= val)
       {
           r = mid;
       }
       else
       {
           l = mid + 1;
       }
    //   cout<<l<<r<<mid<<endl;
   }
  // cout<<endl;
   return r;
}
int main()
{
   scanf("%d", &n);
   build(1, 1, n);
   for(int i = 0; i < n; i ++)
   {
       scanf("%d", a + i);
       b[i] = i + 1;
   }
   sort(b, b + n, cmp);
   scanf("%d", &m);
   for(int i = 0; i < m; i ++)
   {
       scanf("%d%d", &q[i].k, &q[i].p);
       q[i].ind = i;
   }
   sort(q, q + m, cmp1);

   for(int i = 0, j = 0; i < n; i ++)
   {
       add(b[i], 1, 1);
       for(; j < m && q[j].k == i + 1; j ++)
       {
           ans[q[j].ind] = a[work(q[j].p) - 1];
       }
   }
   for(int i = 0; i < m; i ++)
   {
       printf("%d\n", ans[i]);
   }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值