题意:
给定长度为n的排列,m次询问,
每次询问给出L,R,问[L,R]内有多少个数对<i,j>,满足a(i)是a(j)的因子。
数据范围:n,m<=2e5
题意:
因为是排列,所以满足条件的序列只有nlogn种,
预处理出序列中的所有答案数对,
那么问题变为[L,R]内有多少个答案数对<i,j>,
即求有多少个数对<i,j>满足j<=R,且i>=L,这是二维偏序问题,
对于满足询问[L,R]的数对,一定也满足[L,R+1],因此R是单调的,
对询问按照R排序,将所有<i,j>中j<=R的答案数对的i加入BIT,
每个i代表一个数对,那么当前询问的答案就是ask(R)-aks(L-1)
因为n只有1e5,所以代码中用了桶,去掉了排序过程.
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=2e5+5;
vector<int>g[maxm];
vector<PI>q[maxm];
int ans[maxm];
int pos[maxm];
int a[maxm];
int n,m;
struct BIT{
int c[maxm];
int lowbit(int i){
return i&-i;
}
void add(int i,int t){
while(i<maxm){
c[i]+=t;
i+=lowbit(i);
}
}
int ask(int i){
int ans=0;
while(i){
ans+=c[i];
i-=lowbit(i);
}
return ans;
}
}T;
signed main(){
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
pos[a[i]]=i;
}
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j+=i){
int lc=pos[i],rc=pos[j];
if(lc>rc)swap(lc,rc);
g[rc].push_back(lc);
}
}
for(int i=1;i<=m;i++){
int l,r;cin>>l>>r;
q[r].push_back({l,i});
}
for(int i=1;i<=n;i++){
for(auto x:g[i]){
T.add(x,1);
}
for(auto x:q[i]){
ans[x.second]=T.ask(i)-T.ask(x.first-1);
}
}
for(int i=1;i<=m;i++){
cout<<ans[i]<<endl;
}
return 0;
}