2019徐州网络赛 query

题意:

给定一个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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/bxd123/p/11482514.html