题意:
给定一个1-n的全排列 有m个询问l r 问l-r (包括l r) 之间有多少点对i j (i!=j ) 使得 i j 互为倍数关系
先预处理所有的点对 L R 在R位置放入L
然后树状数组遍历即可 当读到R的时候放入L即可
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) // const int N=2e6+10; int n,m,t[N],a[N],pos[N],l,r,ans[N]; void add(int x,int v){for(;x<=N-10;x+=x&-x)t[x]+=v;} int qsum(int x){int ans=0;for(;x;x-=x&-x)ans+=t[x];return ans;} vector<int>table[N]; struct node{int id,l;}; vector<node>qq[N]; int main() { cin>>n>>m; rep(i,1,n) { scanf("%d",&a[i]);pos[a[i]]=i; } rep(i,1,n) for(int j=2*a[i];j<=n;j+=a[i])table[max(pos[j],i)].push_back(min(pos[j],i)); rep(i,1,m) scanf("%d%d",&l,&r),qq[r].push_back({i,l}); rep(i,1,n) { for(auto v:table[i])add(v,1); for(auto v:qq[i])ans[v.id]=qsum(i)-qsum(v.l-1); } rep(i,1,m) printf("%d\n",ans[i]); return 0; }