Edu41
基本情况
D卡太久了,第一次搞计算几何没经验
D. Pair Of Lines
思路不难,重要的是以后计算这种叉乘一定要开longlong
E. Tufurama
-
我们维护一个存储下标数据的树状数组,先将 \(1\sim n\) 插入树状数组。
-
用 \(a\) 表示原数组,\(b\) 表示按照 \(a_i\) 排序后的数组。
-
我们从 \(1\) 开始统计,直到 \(n\),统计时:
-
将 \(i\) 删除,不能把自己算进去。
-
为了排除 \(a_j < i\) 的部分,可以从前往后扫描 \(b\),一直删,直到 \(b_{\text{cur}} \geq i\),
因为 \(b\) 单调不下降,所以 \(i\) 都用不着了, \(i + 1\) 也用不着了。
-
调查 \(a_i \geq j\) 的部分,调用 \(\text{query}(a_i)\) 即可。
-
注意:排除的时候用 \(b\),这样就不用遍历整个 \(a\) 数组来排除 \(a_j < i\) 的部分;
而询问的时候要用 \(a\),因为询问的是 \(a_i \geq j\) 的部分。
-
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (auto& x : a) std::cin >> x, --x;
std::vector<std::pair<int, int>> b(n);
for (int i = 0; i < n; i++) {
b[i].first = a[i], b[i].second = i;
}
Fenwick<i64> T(n);
for (int i = 0; i < n; i++) {
T.add(i, 1);
}
std::sort(all(b));
int cur(0);
i64 ans(0);
std::vector<bool> del(n);
for (int i = 0; i < n; i++) {
if (not del[i]) {//先把当前删了
del[i] = true;
T.add(i, -1);
}
while(cur < n and b[cur].first < i) {//把所有不符合条件(a_j < i)的都删了
if (not del[b[cur].second]) {
del[b[cur].second] = true;
T.add(b[cur].second, -1);
}
cur++;
}
ans += T.sum(std::min(n, a[i] + 1));//查找所有小于等于a_i的元素
}
std::cout << ans << '\n';
}