分析:注意非常重要的一点就是整个数列是一个排列,这样对于一个1到n的排列成倍数关系的数其实是非常少的,大概是nlogn这个数量级,所以我们先把所有成倍关系的两元组求出来,这样设其中下标较大的下标为x,较小的为y,那么问题就转化为了每次求一段区间l到r中包含的成对的[x,y]的个数,这个问题有一个经典的离线做法,从左向右扫描序列,每次把小于当前位置i的y对应的x更新到树状数组里边,那么对于r = i的询问,其答案就是sum(r) - sum(l-1).
#include<bits/stdc++.h>
#define N 200005
using namespace std;
typedef pair<int,int> pii;
vector<int> G[N];
vector<pii> ask[N];
int n,m,x,p[N],f[N],ans[N];
void Insert(int x)
{
int p = x;
while(p <= n)
{
f[p]++;
p += p & (-p);
}
}
int Sum(int x)
{
int p = x,ans = 0;
while(p)
{
ans += f[p];
p -= p & (-p);
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
{
scanf("%d",&x);
p[x] = i;
}
for(int i = 1;i <= n;i++)
for(int j = i;j <= n;j+=i)
{
int x = p[i],y = p[j];
if(x > y) swap(x,y);
G[y].push_back(x);
}
for(int i = 1;i <= m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
ask[r].push_back(make_pair(l,i));
}
for(int i = 1;i <= n;i++)
{
for(int v : G[i]) Insert(v);
for(pii v : ask[i]) ans[v.second] = Sum(i) - Sum(v.first-1);
}
for(int i = 1;i <= m;i++) cout<<ans[i]<<endl;
}