-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
187 lines (167 loc) · 5.28 KB
/
main.cpp
File metadata and controls
187 lines (167 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Source: https://leetcode.com/problems/count-subarrays-with-more-ones-than-zeros
// Title: Count Subarrays With More Ones Than Zeros
// Difficulty: Medium
// Author: Mu Yang <http://muyang.pro>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// You are given a binary array `nums` containing only the integers `0` and `1`. Return the number of **subarrays** in nums that have **more** `1`'s than `0`'s. Since the answer may be very large, return it **modulo** `10^9 + 7`.
//
// A **subarray** is a contiguous sequence of elements within an array.
//
// **Example 1:**
//
// ```
// Input: nums = [0,1,1,0,1]
// Output: 9
// Explanation:
// The subarrays of size 1 that have more ones than zeros are: [1], [1], [1]
// The subarrays of size 2 that have more ones than zeros are: [1,1]
// The subarrays of size 3 that have more ones than zeros are: [0,1,1], [1,1,0], [1,0,1]
// The subarrays of size 4 that have more ones than zeros are: [1,1,0,1]
// The subarrays of size 5 that have more ones than zeros are: [0,1,1,0,1]
// ```
//
// **Example 2:**
//
// ```
// Input: nums = [0]
// Output: 0
// Explanation:
// No subarrays have more ones than zeros.
// ```
//
// **Example 3:**
//
// ```
// Input: nums = [1]
// Output: 1
// Explanation:
// The subarrays of size 1 that have more ones than zeros are: [1]
// ```
//
// **Constraints:**
//
// - `1 <= nums.length <= 10^5`
// - `0 <= nums[i] <= 1`
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <vector>
using namespace std;
// Prefix Sum, TLE
//
// Let pre[i] = #ones - #zeros in [0, i).
// Next loop for all possible subarrays [i, j).
// If pre[j] - pre[i] > 0, then this subarrays has more ones.
class Solution {
constexpr static int modulo = 1e9 + 7;
public:
int subarraysWithMoreOnesThanZeroes(const vector<int>& nums) {
const int n = nums.size();
// Prefix sum
auto pres = vector<int>(n + 1);
for (int i = 0; i < n; ++i) {
pres[i + 1] = pres[i] + (nums[i] ? 1 : -1);
}
// Subarrays
int count = 0;
for (int j = 1; j <= n; ++j) {
for (int i = 0; i < j; ++i) {
count = (count + (pres[j] - pres[i] > 0)) % modulo;
}
}
return count;
}
};
// Prefix Sum + Tree Set
//
// Let pre[i] = #ones - #zeros in [0, i).
// We store pre[i] in a tree set.
// Now count the valid subarrays [i, j) for each fixed j.
// We need to find the number of pre[i] < pre[j] with i < j.
//
// We do insert and count together with single pass.
// For each step j,
// we first compute the number elements less than pre[j] in the tree set;
// next we put pre[j] into the tree set.
//
// However, since C++'s tree set doesn't support lower bound count, we give up this approach.
class Solution2 {};
// Prefix Sum + Fenwick Tree
//
// Let pre[i] = #ones - #zeros in [0, i).
// Note that -n <= pre[i] <= n, where n = len(nums).
// We can create a Fenwick Tree with range [-n, n].
//
// Now follows the same approach as Tree Set's.
// We maps the value range of pre[i] to the index range of the Fenwick Tree.
class Solution3 {
constexpr static int modulo = 1e9 + 7;
struct FenwickTree {
const int m;
vector<int> tree; // tree[i] = sum [i-lowbit(i), i)
FenwickTree(int m) : m(m), tree(m + 1, 0) {}
// O(log n); data[i] += delta
void update(int idx, int delta) {
for (int i = idx + 1; i <= m; i += (i & -i)) {
tree[i] += delta;
}
}
// O(log n); sum of [0, r)
int query(int r) {
int sum = 0;
for (int i = r; i >= 1; i -= (i & -i)) {
sum += tree[i];
}
return sum;
}
};
public:
int subarraysWithMoreOnesThanZeroes(const vector<int>& nums) {
const int n = nums.size();
auto tree = FenwickTree(2 * n + 1); // [-n, n]
// Loop
int count = 0;
int pre = n; // shift n since the original range is [-n, n]
tree.update(pre, 1); // sum of [0, 0)
for (int j = 0; j < n; ++j) {
pre += (nums[j] ? 1 : -1); // sum of [0, j]
count = (count + tree.query(pre)) % modulo;
tree.update(pre, 1);
}
return count;
}
};
// Prefix Sum + Frequency Array
//
// Let pre[i] = #ones - #zeros in [0, i).
// Note that -n <= pre[i] <= n, where n = len(nums).
//
// Since pre[i] only increase or decrease by one in each step,
// we don't need O(log n) to find the count in above approaches.
//
// We store the frequency pre[i] in an array freq (i.e. the underlying data of Fenwick Tree).
// freq[k] = #(pre[i]=k), k in [-n, n].
// We store the count of the pre[i] values less than pre[j] in a variable,
// and use freq[k] to update it.
class Solution4 {
constexpr static int modulo = 1e9 + 7;
public:
int subarraysWithMoreOnesThanZeroes(const vector<int>& nums) {
const int n = nums.size();
auto freqs = vector<int>(2 * n + 1); // [-n, n]
// Loop
int count = 0;
int pre = n; // shift n since the original range is [-n, n]
++freqs[pre]; // sum of [0, 0)
int subcount = 0; // number of pre[i] < current `pre`
for (int j = 0; j < n; ++j) {
if (nums[j] == 1) {
subcount += freqs[pre++];
} else {
subcount -= freqs[--pre];
}
count = (count + subcount) % modulo;
++freqs[pre];
}
return count;
}
};