赞
踩
original link - https://nanti.jisuanke.com/t/41391
题意:
给出一个n的排序,每次查询 [ L , R ] [L,R] [L,R],求区间内有多少对数满足一个是另外一个的因子。
解析:
相当于有 n l o g n nlogn nlogn个对子,我们从后往前,查询到 i i i后,加入以 i i i为左端点的区间的右端点到树状数组,再查询一下有多少个数在区间内即可。
代码:
#include<bits/stdc++.h> #define rep(i,a,b) for(int i = (int)a;i<=(int)b;i++) #define pb push_back using namespace std; typedef long long ll; typedef pair<int,int> pii; const int maxn=100005; const int inf=0x3f3f3f3f; vector<int> Add[maxn]; vector<pii> Q[maxn]; int n,m,a[maxn],pos[maxn]; int ans[maxn],sum[maxn<<1+3]; int lowbit(int x){ return x&(-x); } void add(int p){ while(p<maxn*2){ sum[p]+=1; p+=lowbit(p); } } int query(int p){ int ret=0; while(p){ ret+=sum[p]; p-=lowbit(p); } return ret; } int main(){ scanf("%d%d",&n,&m); rep(i,1,n){ scanf("%d",&a[i]); pos[a[i]]=i; } for(int i=1;i<=n;i++){ for(int j=2*a[i];j<=n;j+=a[i]){ if(pos[j]>i) { Add[i].pb(pos[j]); } else Add[pos[j]].pb(i); } } rep(i,1,m){ int l,r; scanf("%d%d",&l,&r); Q[l].push_back({r,i}); } for(int i=n;i>=1;i--){ for(auto pos:Add[i]){ //printf("i = %d pos = %d\n",i,pos); add(pos); } for(auto pa:Q[i]){ //printf("i= %d r = %d id = %d\n",i,pa.first,pa.second); ans[pa.second]=query(pa.first); } } for(int i=1;i<=m;i++){ printf("%d\n",ans[i]); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。