思路:

首先对于单个查询(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. Win32 Error

    一.Win32错误 也就是Win32子系统产生的错误.当我们在自己的代码里调用Windows系统的API函数,系统执行API内部代码,当API内部代码出现错误,会将预先定义好的错误代码写到调用这个AP ...

  2. leetcode解题报告(28):Remove Linked List Elements

    描述 Remove all elements from a linked list of integers that have value val. Example Given: 1 --> 2 ...

  3. Transformer 比较好的博客

    1. https://www.jianshu.com/p/0c196df57323 细节理解: 2. https://zhuanlan.zhihu.com/p/44121378 3. https:// ...

  4. establish状态,本地ip和端口连接本地ip端口可能是一样的。

    以下是从stackoverflow上抄下来的,很有帮助 How can you have a TCP connection back to the same port? A TCP connectio ...

  5. Pytest权威教程23-不稳定测试

    目录 不稳定测试用例处理 为什么不稳定测试是个问题 潜在的根本原因 Pytest特性 其他一般策略 相关研究 相关资源 返回: Pytest权威教程 不稳定测试用例处理 "不稳定" ...

  6. Java 按字节计算字符串的长度

       在<从后向前截取指定长度的字符串>中介绍了如何截取字符串,本文介绍如何统计字符串的字节长度. import org.slf4j.Logger; import org.slf4j.Lo ...

  7. 第02组 Alpha冲刺(3/6)

    第02组 Alpha冲刺(3/6)   队名:無駄無駄组长博客作业博客 组员情况 张越洋 过去两天完成了哪些任务 摸鱼 提交记录(全组共用) 接下来的计划 沟通前后端成员,监督.提醒他们尽快完成各自的 ...

  8. 第一步,怎么打开react的大门?

    前言 其实我的react的实战经验很少,大概是17年-18年写了一个react全家桶的后台管理系统.猜测这个项目应该还一直在使用 在我手里的vue项目就比较多了,技术栈一直是vue全家桶.最近也在深入 ...

  9. 深入理解JVM虚拟机12:JVM性能管理神器VisualVM介绍与实战

    一.VisualVM是什么? VisualVM是一款免费的JAVA虚拟机图形化监控分析工具. 1.  拥有图形化的监控界面.    2. 提供本地.远程的JVM监控分析功能.    3. 是一款免费的 ...

  10. HTML5+和MUI页面操作

    最近总是碰到针对页面的一些操作,以下是针对webview的一些简单方法以及个人理解.更多详尽的内容请参考标准文档:http://www.html5plus.org/doc/zh_cn/webview. ...