题目链接:query
题意:给出一个长度为n的全排列,q次询问,每次询问区间
[
l
,
r
]
[l,r]
[l,r]内有多少对数字
(
p
,
q
)
(p,q)
(p,q),满足p%q==0。
数据范围
n
,
q
同
阶
1
0
5
n,q同阶10^5
n,q同阶105
数据范围保证了序列是一个全排列,那么可以预处理出所有的满足条件的数字对,这样的数字对数有
∑
i
=
1
n
⌊
x
/
i
⌋
\sum_{i=1}^n\lfloor x/i \rfloor
∑i=1n⌊x/i⌋对,
n
∗
l
o
g
2
n
n*log_2n
n∗log2n。
枚举位置i,假设所有的数字对出现的位置
(
p
,
q
)
,
p
<
q
(p,q),p<q
(p,q),p<q,将所有的满足
q
=
=
i
q==i
q==i的数字对的p位置处加1,对于右区间是i的询问,计算他的答案为ask( r )-ask( l-1 )。
参考自:https://blog.youkuaiyun.com/u014258433/article/details/75675233
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
int sum[maxn];
int n;
void add(int x,int y){
for(;x<=n;x+=x&-x) sum[x]+=y;
}
int ask(int x){
int res=0;
for(;x;x-=x&-x) res+=sum[x];
return res;
}
vector<pair<int,int> >query[maxn];
vector<int> p[maxn];
int pos[maxn];
int ans[maxn];
int main(){
int q,x,y,l,r;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i){
scanf("%d",&x);
pos[x]=i;
}
for(int i=1;i<=n;++i)
for(int j=i;j<=n;j+=i){
x=pos[i],y=pos[j];
if(x<y) swap(x,y);
p[x].push_back(y);
}
for(int i=1;i<=q;++i){
scanf("%d%d",&l,&r);
query[r].push_back(make_pair(l,i));
ans[i]-=r-l+1;
}
for(int i=1;i<=n;++i){
for(int j=0;j<p[i].size();++j) add(p[i][j],1);
for(int j=0;j<query[i].size();++j) ans[query[i][j].second]+=ask(i)-ask(query[i][j].first-1);
}
for(int i=1;i<=q;++i) printf("%d\n",ans[i]);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int a[maxn],pos[maxn];
vector<int> v[maxn];
int sum[maxn];
int n;
void add(int x,int y){
for(;x<=n;x+=x&-x) sum[x]+=y;
}
int ask(int x){
int res=0;
for(;x;x-=x&-x) res+=sum[x];
return res;
}
struct Node{
int l,r,id;
bool operator <(const Node& x)const{
return r<x.r;
}
}b[maxn];
int ans[maxn];
int main(){
int m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
for(int i=1;i<=n;++i)
for(int j=i;j<=n;j+=i){
int x=pos[i],y=pos[j];
if(x<y) swap(x,y);
v[x].push_back(y);
}
for(int i=1;i<=m;++i){
scanf("%d%d",&b[i].l,&b[i].r);
b[i].id=i;
ans[i]-=b[i].r-b[i].l+1;
}
sort(b+1,b+1+m);
for(int i=1,j=1;i<=m;++i){
while(j<=b[i].r){
for(int k=0;k<v[j].size();++k) add(v[j][k],1);
++j;
}
ans[b[i].id]+=ask(b[i].r)-ask(b[i].l-1);
}
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}