满足的 pair 只有 $O(nlogn)$ 对,预处理一下每对的位置,然后离线每个询问,按右端点排序,遇到一个右端点就将所有满足的左端点在树状数组上+1,然后一个询问就用树状数组查询即可。
#include <bits/stdc++.h> const int N = 2e5 + 7; struct Que { int l, r, id; bool operator < (const Que &p) const { return r < p.r; } } que[N]; int n, m, p[N], pos[N]; std::vector<int> vec[N]; int ans[N]; struct Bit { int tree[N]; inline int lowbit(int x) { return x & -x; } inline void add(int x) { for (int i = x; i <= n; i += lowbit(i)) tree[i]++; } inline int query(int x) { int ans = 0; for (int i = x; i; i -= lowbit(i)) ans += tree[i]; return ans; } inline int query(int l, int r) { return query(r) - query(l - 1); } } bit; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", p + i), pos[p[i]] = i; for (int i = 1; i <= n; i++) { for (int j = p[i]; j <= n; j += p[i]) { int l = i, r = pos[j]; if (l > r) std::swap(l, r); vec[r].push_back(l); } } for (int i = 1; i <= m; i++) scanf("%d%d", &que[i].l, &que[i].r), que[i].id = i; std::sort(que + 1, que + 1 + m); int cur = 1; for (int i = 1; i <= m; i++) { while (cur <= que[i].r) { for (int j = 0; j < vec[cur].size(); j++) bit.add(vec[cur][j]); cur++; } ans[que[i].id] = bit.query(que[i].l, que[i].r); } for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0; }
Codeforces Round #182 (Div. 1) D. Yaroslav and Divisors
原文:https://www.cnblogs.com/Mrzdtz220/p/12249082.html