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;
}
posted @ 2020-09-12 22:49  Nylch  阅读(72)  评论(0编辑  收藏  举报