CF1227D Optimal Subsequences
思路:
首先对于单个查询(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的更多相关文章
- 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, ...
- CF-Technocup3 D Optimal Subsequences
D Optimal Subsequences http://codeforces.com/contest/1227/problem/D2 显然,每次求的k一定是这个序列从大到小排序后前k大的元素. 考 ...
- Codeforces 1262D Optimal Subsequences(BIT+二分)
首先比较容易想到肯定是前k大的元素,那么我们可以先对其进行sort,如果数值一样返回下标小的(见题意),接下里处理的时候我们发现需要将一个元素下标插入到有序序列并且需要访问第几个元素是什么,那么我们可 ...
- Optimal Subsequences(主席树)
题意: 给定一个序列,长度为n(<=2e5),有m(<=2e5)个询问,每个询问包含k和pos,要从原序列中选出一个长度为k的子序列,要求是这个序列的和是所有长度为k的序列中最大的,且是字 ...
- D2. Optimal Subsequences (Hard Version) 主席树
题目链接:https://codeforces.com/contest/1262/problem/D2 将数组按大到小排序(相同大小的按下标由小到大排序),依次将排序后的每个数在原数组中的位置放入主席 ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) - D2. Optimal Subsequences (Hard Version)(主席树)
题意:一共有$n$个数,$m$次询问,每次询问包括$k.pos$两个数,需要你从这$n$个数里面找出$k$个数,使得他们的总和最大,如果有多种情况,找出序号字典序最小的一组,然后输出这个序列中第$po ...
- codeforces 1262D Optimal Subsequences 主席树询问第k小
题意 给定长度为\(n\)的序列\(a\),以及m个询问\(<k,pos>\),每次询问满足下列条件的子序列中第\(pos\)位的值为多少. 子序列长度为\(k\) 序列和是所有长度为\( ...
- Codeforces Round #602 Div2 D1. Optimal Subsequences (Easy Version)
题意:给你一个数组a,询问m次,每次返回长度为k的和最大的子序列(要求字典序最小)的pos位置上的数字. 题解:和最大的子序列很简单,排个序就行,但是题目要求字典序最小,那我们在刚开始的时候先记录每个 ...
- 笔记 - 数据结构 - 区间第k大
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2 - Optimal Subsequence ...
随机推荐
- pt
https://www.hdarea.co/torrents.php http://hdhome.org/torrents.php https://ourbits.club/torrents.php ...
- noi.ac #46 最长上升子序列
\(des\) 长度为 \(n\) 的序列 \(A\),从中删去恰好 \(k\) 个元素(右边的元素往左边移动),记 \(cnt\) 为新 序列中 \(Ai = i\) 的元素个数(即权值与下标相同的 ...
- Cogs 763. [USACO Open09] 数字的游戏(博弈)
[USACO Open09] 数字的游戏 ★☆ 输入文件:cdgame.in 输出文件:cdgame.out 简单对比 时间限制:1 s 内存限制:128 MB Bessie正跟FJ玩一个数字游戏,她 ...
- 《挑战30天C++入门极限》C++面向对象编程入门:类(class)
C++面向对象编程入门:类(class) 上两篇内容我们着重说了结构体相关知识的操作. 以后的内容我们将逐步完全以c++作为主体了,这也意味着我们的教程正式进入面向对象的编程了. 前面的教程我 ...
- ZR#1009
ZR#1009 解法: 因为无敌的SR给了一个大暴力算法,所以通过打表发现了了一些神奇的性质,即第一行和第一列的对应位置数值相等. 我们可以通过手算得出 $ F(n) = \frac{n(n + 1) ...
- 利用iterm2,在命令行预览图片,服务器也是可以的
1.首先你本地电脑上要安装iterm2软件,我们这里使用brew安装 这个是一定要装的,因为能在命令行渲染出图片文件全靠它,其实不是服务器渲染出来的,而是iterm2 官方网站:https://www ...
- ubuntu之路——day8.1 深度学习优化算法之mini-batch梯度下降法
所谓Mini-batch梯度下降法就是划分训练集和测试集为等分的数个子集,比如原来有500W个样本,将其划分为5000个baby batch,每个子集中有1000个样本,然后每次对一个mini-bat ...
- JS实现文字向上无缝滚动轮播
效果图: 全部代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- 第2课第3节_Java面向对象编程_继承性_P【学习笔记】
摘要:韦东山android视频学习笔记 面向对象程序的三大特性之继承性:继承性的主要作用就是复用代码.继承性也有一定的限制,如图一 图一 1.我们在第2课第2节_Java面向对象编程_封装性_P 中 ...
- Python: 在CSV文件中写入中文字符
0.2 2016.09.26 11:28* 字数 216 阅读 8053评论 2喜欢 5 最近一段时间的学习中发现,Python基本和中文字符杠上了.如果能把各种编码问题解决了,基本上也算对Pytho ...