CF301D [Yaroslav and Divisors]
首先记 \(sum_i\) 表示 \([1,i]\) 中整除对的数量,那么每次询问的答案就是 \(sum_r-sum_l-\) 左端点在 \([1,l]\),右端点在 \([l,r]\) 的整除对。那么考虑离线处理,对于每个询问 \([l,r]\),当 \(l=i\),\(sum_r-sum_{l-1}=\) 左端点在 \([1,l]\),右端点在 \([l,r]\) 的整除对,然后更新一下 \(sum_i\)。\(sum_i\) 可以用树状数组或者线段树维护一下就好了。
#include <bits/stdc++.h>
#define reg register
#define ll long long
#define ull unsigned long long
#define db double
#define pi pair<int, int>
#define pl pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define vpi vector<pi>
#define vpl vector<pl>
#define pb push_back
#define er erase
#define SZ(x) (int) x.size()
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define mkp make_pair
using namespace std;
char ch, B[1 << 20], *S = B, *T = B;
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 20, stdin), S == T) ? 0 : *S++)
#define isd(c) (c >= '0' && c <= '9')
int aa, bb;
int rd() {
while(ch = getc(), !isd(ch) && ch != '-');
ch == '-' ? aa = bb = 0 : (aa = ch - '0', bb = 1);
while(ch = getc(), isd(ch))
aa = aa * 10 + ch - '0';
return bb ? aa : -aa;
}
const int MAXN = 2e5 + 10;
int n, m, p[MAXN], tr[MAXN], ans[MAXN], pos[MAXN];
struct Node {
int l, r, id;
} a[MAXN], b[MAXN];
bool cmp1(Node a, Node b) {
return a.l == b.l ? a.r < b.r : a.l < b.l;
}
bool cmp2(Node a, Node b) {
return a.r == b.r ? a.l < b.l : a.r < b.r;
}
inline void add(int x, int c) {
while(x <= n) {
tr[x] += c;
x += (x & (-x));
}
}
int sum(int x) {
int ret = 0;
while(x) {
ret += tr[x];
x -= (x & (-x));
}
return ret;
}
inline void work() {
n = rd();
m = rd();
for(reg int i = 1; i <= n; ++i) {
p[i] = rd();
pos[p[i]] = i;
}
for(reg int i = 1; i <= m; ++i) {
int l = rd(), r = rd();
a[i].l = l;
a[i].r = r;
a[i].id = i;
b[i] = a[i];
}
sort(a + 1, a + m + 1, cmp1);
sort(b + 1, b + m + 1, cmp2);
int j = 1, k = 1;
for(reg int i = 1; i <= n; ++i) {
while(a[j].l == i && j <= m) {
ans[a[j].id] -= sum(a[j].r) - sum(a[j].l - 1);
++j;
}
for(reg int l = 1; l * p[i] <= n; ++l)
add(pos[l * p[i]], 1);
while(b[k].r == i && k <= m) {
ans[b[k].id] += sum(b[k].r) - sum(b[k].l - 1);
++k;
}
}
for(reg int i = 1; i <= m; ++i)
// printf("%d %d\n", ans[i], tr[i]);
printf("%d\n", ans[i]);
}
int main() {
// freopen("input.txt", "r", stdin);
work();
return 0;
}