【KickStart】Round H 2019: H-index

起因:本来说好打游戏的人咕咕咕了

题目链接:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050edd/00000000001a274e

一直想多刷题来着,但是总犯懒。今天也只刷了这一道,典型的树状数组题(之前还不太会,现学现用吧……)。简单分析,题目数值范围比较大,需要快速求解大于等于H的数值有多少个,数值有大小范围,可以用一个计数数组存下来,然后树状数组求区间值就可以了。

树状数组简单理解,就是重用区间和。计算当前下标的二进制,有N个0,就往前(包括自己)数2^N个数加和。通过x & (-x)的方式消除二进制最后一个1,然后在新的下标下继续求和。

 1 #include "bits/stdc++.h"
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 int T, N, A[100010], tmp, res, maxVal, l, r, m;
 7 
 8 // 看的别人的树状数组模板,这个class可以不在初始化的时候接受arr的
 9 // 为了以后方便复用还是留着吧(
10 class BinaryIndexedTree {
11 public:
12     vector<int> bitArr;
13 
14     BinaryIndexedTree(int arr[], int l = 0) {
15         bitArr.clear();
16         bitArr.resize(l + 1, 0);
17         for (int i = 0; i < l; ++i) 
18             bitArr[i + 1] = arr[i];
19         int j;
20         for (int i = 1; i <= l; ++i) {
21             j = i + (i & -i);
22             if (j <= l) 
23                 bitArr[j] += bitArr[i];
24         }
25     }
26 
27     void reset(int arr[], int l = 0) {
28         bitArr.clear();
29         bitArr.resize(l + 1, 0);
30         for (int i = 0; i < l; ++i)
31             bitArr[i + 1] = arr[i];
32         int j;
33         for (int i = 1; i <= l; ++i) {
34             j = i + (i & -i);
35             if (j <= l)
36                 bitArr[j] += bitArr[i];
37         }
38     }
39 
40     void update(int idx, int val) {
41         ++idx;
42         while (idx < bitArr.size()) {
43             bitArr[idx] += val;
44             idx += idx & (-idx);
45         }
46     }
47 
48     int prefixSum(int idx) {
49         ++idx;
50         int res = 0;
51         while (idx > 0) {
52             res += bitArr[idx];
53             idx -= idx & (-idx);
54         }
55         return res;
56     }
57 
58     int rangeSum(int withoutLeft, int withRight) {
59         return prefixSum(withRight) - prefixSum(withoutLeft);
60     }
61 };
62 
63 
64 int main() {
65     scanf("%d", &T);
66     BinaryIndexedTree * binIndTree = new BinaryIndexedTree(A);
67     for (int _t = 1; _t <= T; ++_t) {
68         scanf("%d", &N);
69         printf("Case #%d:", _t);
70         res = 0;
71         maxVal = 1;
72 
73         binIndTree->reset(A, 100005);
74         for (int i = 1; i <= N; ++i) {
75             scanf("%d", &tmp);
76             binIndTree->update(tmp, 1);
77             maxVal = max(tmp, maxVal);
78 
79             l = res, r = maxVal;
80             while (l <= r) {
81                 m = (l + r) >> 1;
82                 if (m <= binIndTree->rangeSum(m - 1, maxVal)) {
83                     res = m;
84                     l = m + 1;
85                 }
86                 else {
87                     r = m - 1;
88                 }
89             }
90             printf(" %d", res);
91         }
92         printf("\n");
93     }
94     return 0;
95 }

 

posted @ 2020-07-24 18:06  Katrin  阅读(143)  评论(0编辑  收藏  举报