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 }
  • 相关阅读:
    基本MVVM 和 ICommand用法举例(转)
    WPF C# 命令的运行机制
    628. Maximum Product of Three Numbers
    605. Can Place Flowers
    581. Shortest Unsorted Continuous Subarray
    152. Maximum Product Subarray
    216. Combination Sum III
    448. Find All Numbers Disappeared in an Array
    268. Missing Number
    414. Third Maximum Number
  • 原文地址:https://www.cnblogs.com/wangyiming/p/11989636.html
Copyright © 2011-2022 走看看