zoukankan      html  css  js  c++  java
  • 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)):

     1 #include <bits/stdc++.h>
     2  
     3 using namespace std;
     4 const int MAXN = 200000;
     5 typedef pair<int, int> pii;
     6  
     7 int a[MAXN + 5], bit[MAXN + 5];
     8  
     9 int lowbit(int x) { return x & -x; }
    10  
    11 void add(int i, int x)
    12 {
    13     while (i <= MAXN) { bit[i] += x; i += lowbit(i); }
    14 }
    15  
    16 int sum(int i)
    17 {
    18     int ans = 0;
    19     while (i) { ans += bit[i]; i -= lowbit(i); }
    20     return ans;
    21 }
    22  
    23 bool cmp(pii& a, pii& b)
    24 {
    25     if (a.first != b.first) return a.first > b.first;
    26     return a.second < b.second; 
    27 }
    28  
    29 void work(pii& q, map<pii, int>& mp)
    30 {
    31     int k = q.first, p = q.second;
    32     int l = 1, r = MAXN, res = -1;
    33     while (l <= r)
    34     {
    35         int m = l + r >> 1;
    36         if (sum(m) < p) l = m + 1;
    37         else { res = m; r = m - 1; }
    38     }
    39     assert(res != -1);
    40     mp[q] = res;
    41 }
    42  
    43 int main()
    44 {
    45     ios::sync_with_stdio(false);
    46     int n, m;
    47     while (cin >> n)
    48     {
    49         memset(bit, 0, sizeof bit);
    50         vector<int> a(n);
    51         for (int i = 0; i < n; i++) cin >> a[i];
    52         vector<pii> b(n);
    53         for (int i = 0; i < n; i++) { b[i].first = a[i]; b[i].second = i + 1; }
    54         sort(b.begin(), b.end(), cmp);
    55         cin >> m;
    56         vector<pii> q(m);
    57         for (int i = 0; i < m; i++) cin >> q[i].first >> q[i].second;
    58         vector<pii> sorted_q(q.begin(), q.end());
    59         sort(sorted_q.begin(), sorted_q.end());
    60         map<pii, int> res;
    61         int cur = 0;
    62         for (int i = 0; i < n; i++)
    63         {
    64             add(b[i].second, 1);
    65             while (cur < m && i + 1 == sorted_q[cur].first)
    66             {
    67                 work(sorted_q[cur], res);
    68                 cur++;
    69             }
    70         }
    71         for (auto it: q)
    72         {
    73             int id = res[it];
    74             cout << a[id - 1] << endl;
    75         }
    76     }
    77     return 0;
    78 }

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

     1 #include <bits/stdc++.h>
     2  
     3 #include <ext/pb_ds/assoc_container.hpp>
     4 #include <ext/pb_ds/tree_policy.hpp>
     5  
     6 using namespace std;
     7 using namespace __gnu_pbds;
     8  
     9 typedef pair<int, int> pii;
    10 typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
    11  
    12 bool cmp(pii& a, pii& b)
    13 {
    14     if (a.first != b.first) return a.first > b.first;
    15     return a.second < b.second; 
    16 }
    17  
    18 int main()
    19 {
    20     ios::sync_with_stdio(false);
    21     int n, m;
    22     while (cin >> n)
    23     {
    24         vector<int> a(n);
    25         for (int i = 0; i < n; i++) cin >> a[i];
    26         vector<pii> b(n);
    27         for (int i = 0; i < n; i++) { b[i].first = a[i]; b[i].second = i + 1; }
    28         sort(b.begin(), b.end(), cmp);
    29         cin >> m;
    30         vector<pii> q(m);
    31         for (int i = 0; i < m; i++) cin >> q[i].first >> q[i].second;
    32         vector<pii> sorted_q(q.begin(), q.end());
    33         sort(sorted_q.begin(), sorted_q.end());
    34         map<pii, int> res;
    35         int cur = 0;
    36         ordered_set st;
    37         for (int i = 0; i < n; i++)
    38         {
    39             st.insert(b[i].second);
    40             while (cur < m && i + 1 == sorted_q[cur].first)
    41             {
    42                 res[sorted_q[cur]] = *st.find_by_order(sorted_q[cur].second - 1);
    43                 cur++;
    44             }
    45         }
    46         for (auto it: q)
    47         {
    48             cout << a[res[it] - 1] << endl;
    49         }
    50     }
    51 }
  • 相关阅读:
    俺自己可以写点代码了
    学姐,孙哥
    Linux/Unix 常用参数使用说明
    DB2 rollforward 命令使用详解
    DB2 create tablespace
    db2 基础语法
    VMWARE虚拟机不显示主机共享的文件夹解决办法
    DB2创建数据库常用参数详解
    从Linux访问Windows共享目录
    Data Flow >> Source >> Error Output >> Error & Truncation: Ignore Failure, Redirect Now, Fail Component
  • 原文地址:https://www.cnblogs.com/wangyiming/p/11989636.html
Copyright © 2011-2022 走看看