思路:

首先对于单个查询(k, p)来说,答案一定是a数组中的前k大数。如果第k大的数字有多个怎么办?取索引最小的若干个。所以我们只需对a数组按照值降序,索引升序排序即可。

多个查询怎么办?离线处理。依然是对数组a按照上面的方法排序,然后对所有的查询按照k升序排序,分别离线计算。具体做法是,按顺序扫描a,用一个集合动态维护前k大的数,当发现某个查询正好询问前k大时,即时处理即可。

那么如何从一个集合中快速找到第k大数?c++标准库中原始的set是不行的,可以用1. 二分+树状数组(或线段树)2. __gnu_pbds https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/

实现1(二分+树状数组,n * log(n) * log(n)):

 #include <bits/stdc++.h>

 using namespace std;
const int MAXN = ;
typedef pair<int, int> pii; int a[MAXN + ], bit[MAXN + ]; int lowbit(int x) { return x & -x; } void add(int i, int x)
{
while (i <= MAXN) { bit[i] += x; i += lowbit(i); }
} int sum(int i)
{
int ans = ;
while (i) { ans += bit[i]; i -= lowbit(i); }
return ans;
} bool cmp(pii& a, pii& b)
{
if (a.first != b.first) return a.first > b.first;
return a.second < b.second;
} void work(pii& q, map<pii, int>& mp)
{
int k = q.first, p = q.second;
int l = , r = MAXN, res = -;
while (l <= r)
{
int m = l + r >> ;
if (sum(m) < p) l = m + ;
else { res = m; r = m - ; }
}
assert(res != -);
mp[q] = res;
} int main()
{
ios::sync_with_stdio(false);
int n, m;
while (cin >> n)
{
memset(bit, , sizeof bit);
vector<int> a(n);
for (int i = ; i < n; i++) cin >> a[i];
vector<pii> b(n);
for (int i = ; i < n; i++) { b[i].first = a[i]; b[i].second = i + ; }
sort(b.begin(), b.end(), cmp);
cin >> m;
vector<pii> q(m);
for (int i = ; i < m; i++) cin >> q[i].first >> q[i].second;
vector<pii> sorted_q(q.begin(), q.end());
sort(sorted_q.begin(), sorted_q.end());
map<pii, int> res;
int cur = ;
for (int i = ; i < n; i++)
{
add(b[i].second, );
while (cur < m && i + == sorted_q[cur].first)
{
work(sorted_q[cur], res);
cur++;
}
}
for (auto it: q)
{
int id = res[it];
cout << a[id - ] << endl;
}
}
return ;
}

实现2(__gnu_pbds,n * log(n)):

 #include <bits/stdc++.h>

 #include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp> using namespace std;
using namespace __gnu_pbds; typedef pair<int, int> pii;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set; bool cmp(pii& a, pii& b)
{
if (a.first != b.first) return a.first > b.first;
return a.second < b.second;
} int main()
{
ios::sync_with_stdio(false);
int n, m;
while (cin >> n)
{
vector<int> a(n);
for (int i = ; i < n; i++) cin >> a[i];
vector<pii> b(n);
for (int i = ; i < n; i++) { b[i].first = a[i]; b[i].second = i + ; }
sort(b.begin(), b.end(), cmp);
cin >> m;
vector<pii> q(m);
for (int i = ; i < m; i++) cin >> q[i].first >> q[i].second;
vector<pii> sorted_q(q.begin(), q.end());
sort(sorted_q.begin(), sorted_q.end());
map<pii, int> res;
int cur = ;
ordered_set st;
for (int i = ; i < n; i++)
{
st.insert(b[i].second);
while (cur < m && i + == sorted_q[cur].first)
{
res[sorted_q[cur]] = *st.find_by_order(sorted_q[cur].second - );
cur++;
}
}
for (auto it: q)
{
cout << a[res[it] - ] << endl;
}
}
}

CF1227D Optimal Subsequences的更多相关文章

  1. Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心

    D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, ...

  2. CF-Technocup3 D Optimal Subsequences

    D Optimal Subsequences http://codeforces.com/contest/1227/problem/D2 显然,每次求的k一定是这个序列从大到小排序后前k大的元素. 考 ...

  3. Codeforces 1262D Optimal Subsequences(BIT+二分)

    首先比较容易想到肯定是前k大的元素,那么我们可以先对其进行sort,如果数值一样返回下标小的(见题意),接下里处理的时候我们发现需要将一个元素下标插入到有序序列并且需要访问第几个元素是什么,那么我们可 ...

  4. Optimal Subsequences(主席树)

    题意: 给定一个序列,长度为n(<=2e5),有m(<=2e5)个询问,每个询问包含k和pos,要从原序列中选出一个长度为k的子序列,要求是这个序列的和是所有长度为k的序列中最大的,且是字 ...

  5. D2. Optimal Subsequences (Hard Version) 主席树

    题目链接:https://codeforces.com/contest/1262/problem/D2 将数组按大到小排序(相同大小的按下标由小到大排序),依次将排序后的每个数在原数组中的位置放入主席 ...

  6. Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) - D2. Optimal Subsequences (Hard Version)(主席树)

    题意:一共有$n$个数,$m$次询问,每次询问包括$k.pos$两个数,需要你从这$n$个数里面找出$k$个数,使得他们的总和最大,如果有多种情况,找出序号字典序最小的一组,然后输出这个序列中第$po ...

  7. codeforces 1262D Optimal Subsequences 主席树询问第k小

    题意 给定长度为\(n\)的序列\(a\),以及m个询问\(<k,pos>\),每次询问满足下列条件的子序列中第\(pos\)位的值为多少. 子序列长度为\(k\) 序列和是所有长度为\( ...

  8. Codeforces Round #602 Div2 D1. Optimal Subsequences (Easy Version)

    题意:给你一个数组a,询问m次,每次返回长度为k的和最大的子序列(要求字典序最小)的pos位置上的数字. 题解:和最大的子序列很简单,排个序就行,但是题目要求字典序最小,那我们在刚开始的时候先记录每个 ...

  9. 笔记 - 数据结构 - 区间第k大

    Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2 - Optimal Subsequence ...

随机推荐

  1. BZOJ 2064: 分裂 状压动归

    最多的操作次数是 $n+m-1$ (相当于把第一个暴力合并,再暴力拆成第二个).如果第一个序列的一个子序列和第二个区间的子序列相等,那么总次数就可以减 $2$.将第二个序列所有数取反,直接求解有多少个 ...

  2. cube.js 学习(一)简单项目创建

    cube.js 是一个很不错的模块化分析框架,基于schema生成sql 同时内置可代码生成,可以快速的搞定 web 分析应用的开发 安装cli 工具 npm install -g cubejs-cl ...

  3. ipkg-nas

    http://pkg.entware.net/binaries/x86-64/ https://forum.synology.com/enu/viewtopic.php?t=95346 http:// ...

  4. codevs1504愚蠢的组合数 / RQNOJ愚蠢的组合数

    1504 愚蠢的组合数  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 最近老师教了狗狗怎么算组合数,狗狗又 ...

  5. 洛谷 P1807 最长路_NOI导刊2010提高(07) 题解

    P1807 最长路_NOI导刊2010提高(07) 题目描述 设G为有n个顶点的有向无环图,G中各顶点的编号为1到n,且当为G中的一条边时有i < j.设w(i,j)为边的长度,请设计算法,计算 ...

  6. python生成词云

    上代码: # -*- coding: utf-8 -*- # @Time : 19-1-10 上午10:27 # @Author : Felix Wang import jieba # pip ins ...

  7. Linux 系统安装下安装 mysql5.7(glibc版)

    转自:https://www.cnblogs.com/mujingyu/p/7689116.html 前言:经过一天半的折腾,终于把 mysql 5.7.17 版本安装上了 centos 7 系统上, ...

  8. 项目管理、bug管理工具 ---禅道使用流程

    使用前描述: 禅道是付费的一款云平台工具,它可以实现项目管理.需求管理.bug提交.bug跟踪.文档管理.bug统计等功能 使用账号.密码:公司提供,登录后基本识别操作流程如下: 1.登录首页-我的地 ...

  9. rocketMq和kafka的架构区别

    概述 其实一直想写一篇rocketMq和kafka在架构设计上的差别,但是一直有个问题没搞明白所以迟迟没动手,今天无意中听人点播了一下似乎明白了这个问题,所以就有了这篇对比. 这篇博文主要讲清楚kaf ...

  10. Redis哨兵日志说明

    一.说明