H1. Maximum Crossings (Easy Version)
https://codeforces.com/problemset/problem/1676/H1
题意:给定上下两排长度为n的数组,第一排的发送了射线到第二排的某个位置,两个点发送到了相同的位置,那么这两个点可以在这个位置按自定义顺序前后顺序排列。问发出的射线中交点最多可能是多少。
思路:树状数组,从前往后依次考虑每个点,统计后面有多少个点发送的射线的位置<=当前点发出的射线位置,该数量就是当前点发出射线与其他点射线的交点数量。
总结:树状数组真不错,位置+就是更新当前位置和一直+lowbit()的新位置,前缀和也是当前位置一直-lowbit的新位置
/*
* FenwickTree(树状数组)
* 设计思想:基于二进制表示的下标的快速变换来实现前缀和的计算,适用于差分后的区间修改单点查询,单点修改区间查询。
* 基于面向对象的编程思想,本方法尽可能多的隐藏了内部实现的细节,并且将必要的编程接口暴露在外部,并需要对这些接口进行直接的修改。
* 在该设计中,基础的方法都已实现,如有需要用户可以自行在该结构上进行改进。
*
* gitHub(仓库地址): https://github.com/yxc-s/programming-template.git
*/
/*
该树总是约定区间左端点从1开始(避免lowbit(0)的情况)。
如果已有数组,建议使用已有的数组实例化对象,时间复杂度更低。
注意初始化数组时容器为int和longlong的区别。
*/
class FenwickTree {
public:
/* 按区间最大右端点下标构造。*/
FenwickTree(unsigned int n) : n_(n) {
ft_.resize(n_);
}
/* 基于已有的数组构造。*/
FenwickTree(const std::vector<long long>& f) {
n_ = static_cast<int>(f.size());
ft_.assign(n_, 0);
for (int i = 1; i < n_; ++i) {
ft_[i] += f[i];
if (i + lowbit(i) < n_) {
ft_[i + lowbit(i)] += ft_[i];
}
}
}
/* 移动构造,减少一次资源分配 */
FenwickTree(std::vector<long long>&& f) {
n_ = static_cast<int>(f.size());
ft_ = std::move(f);
for (int i = 1; i < n_; ++i) {
if (i + lowbit(i) < n_) {
ft_[i + lowbit(i)] += ft_[i];
}
}
}
/* 按数组元素出现频次构造*/
FenwickTree(const std::vector<int>& s) {
n_ = *std::max_element(s.begin() + 1, s.end()) + 1;
ft_.resize(n_);
for (size_t i = 1; i < s.size(); ++i) {
ft_[s[i]]++;
if (s[i] + lowbit(s[i]) < n_) {
ft_[s[i] + lowbit(s[i])] += ft_[s[i]];
}
}
}
/* 单点更新。 */
void update(int pos, long long value) {
assert(pos > 0);
while (pos < n_) {
ft_[pos] += value;
pos += lowbit(pos);
}
}
/* 区间更新。*/
void update(int l, int r, long long value) {
assert(l > 0 && r >= l);
update(l, value);
update(r + 1, -value);
}
/* 单点查询。*/
long long query(int p) {
assert(p < n_);
long long res = 0;
while (p > 0) {
res += ft_[p];
p -= lowbit(p);
}
return res;
}
/* 区间查询。*/
long long query(int l, int r) {
assert(l <= r);
return query(r) - query(l - 1);
}
private:
int n_;
std::vector<long long> ft_;
private:
int lowbit(int x) const noexcept{ return (x & (-x)); }
};
using namespace std;
inline void preProcess() {
}
inline void solve() {
int n;
cin >> n;
FenwickTree ft(n + 1);
vector<int> a(n);
for (auto& x : a) {
cin >> x;
ft.update(x, 1);
}
long long ans = 0;
for (const auto& x : a) {
ft.update(x, -1);
ans += ft.query(x);
}
cout << ans << '\n';
}

浙公网安备 33010602011771号