题目
样例
数据
1 <= flowers.length <= 5 * 104
1 <= starti <= endi <= 109
1 <= persons.length <= 5 * 104
1 <= persons[i] <= 109
题解
map差分 + 双指针
思路:
- [ s t a r t i , e n d i ] 区 间 每 个 时 间 点 都 多 一 朵 花 , 计 算 p e r s o n i 时 间 点 的 花 数 {[start_i, end_i]区间每个时间点都多一朵花,计算person_i时间点的花数} [starti,endi]区间每个时间点都多一朵花,计算personi时间点的花数。
- 利用map差分思路, s t a r t 增 加 1 , e n d + 1 减 少 1 {start增加1,end + 1减少1} start增加1,end+1减少1。
iota(id)
是 p e r s o n {person} person排序的对应下标数组。- 从小到大遍历 m p {mp} mp,指针同从小到大移动到 p e r s o n i {person_i} personi时间点。
class Solution {
public:
vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& persons) {
map<int, int> mp;
for (auto &x: flowers) mp[x[0]]++, mp[x[1] + 1]--;
vector<int> id(persons.size());
iota(id.begin(), id.end(), 0);
sort(id.begin(), id.end(), [&](int i, int j){ return persons[i] < persons[j]; });
vector<int> ans(persons.size());
auto it = mp.begin();
int sum = 0;
for (int i = 0; i < id.size(); i++) {
while(it != mp.end() && it->first <= persons[id[i]]) sum += it++->second;
ans[id[i]] = sum;
}
return ans;
}
};
二分(清晰透彻)
思路:
- 正在开的花的个数 = 所有在此时间节点及之前开放的花的个数 - 在时间节点之前凋谢的花的个数
class Solution {
public:
vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& persons) {
int n = flowers.size();
vector<int> open(n), close(n);
for (int i = 0; i < n; i++) open[i] = flowers[i][0], close[i] = flowers[i][1];
sort(open.begin(), open.end());
sort(close.begin(), close.end());
vector<int> ans;
for (int i = 0; i < persons.size(); i++) {
int now = persons[i];
int op = upper_bound(open.begin(), open.end(), now) - open.begin();
int cl = upper_bound(close.begin(), close.end(), now - 1) - close.begin();
ans.push_back(op - cl);
}
return ans;
}
};
差分 + 树状数组 + 哈希
哈希树状数组
- 注释正常思路,对开花,谢花,人到的时间点都标记,排序。
- 但数据太大, t r {tr} tr数组维护不了1e9的长度
时间开销大
class Solution {
public:
static constexpr int N = 1e9 + 7;
// int tr[N];
unordered_map<int, int> tr;
void add(int x, int c = 1) {
for (; x <= N; x += x & -x) tr[x] += c;
}
int sum(int x) {
int res = 0;
for (; x; x -= x & -x) res += tr[x];
return res;
}
// #define INF 0x3f3f3f3f
vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& persons) {
int n = flowers.size();
// vector<pair<int, int>> v;
// for (int i = 0; i < n; i++) v.push_back({flowers[i][0], -INF}), v.push_back({flowers[i][1], INF});
// for (int i = 0; i < persons.size(); i++) v.push_back({persons[i], i});
// sort(v.begin(), v.end());
for (auto &x: flowers) add(x[0], 1), add(x[1] + 1, -1); // 从这之后少1,差分嘛
vector<int> ans(persons.size());
for (int i = 0; i < persons.size(); i++) {
// auto x = v[i];
// if(x.second == -INF) add(x.first, 1);
// else if(x.second == INF) add(x.first + 1, -1);
// else ans[x.second] = sum(x.first);
ans[i] = sum(persons[i]);
}
return ans;
}
};
离散化 + 前缀和 (简洁明了)
思路:
- 离散化(map)后, c n t < = 3 ∗ 5 e 4 {cnt<=3 * 5e4} cnt<=3∗5e4
- 直接前缀和求得答案。
class Solution {
public:
map<int, int> a, id;
int s[150010];
int cnt = 0;
vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& persons) {
for (auto &x: flowers) a[x[0]] = 1, a[x[1] + 1] = 1;
for (auto &x: persons) a[x] = 1;
for (auto &x: a) id[x.first] = ++cnt;
for (auto &x: flowers) s[id[x[0]]]++, s[id[x[1] + 1]]--;
for (int i = 1; i <= cnt; i++) s[i] += s[i - 1];
vector<int> res;
for (auto &x: persons) res.push_back(s[id[x]]);
return res;
}
};