原题: http://codeforces.com/problemset/problem/301/D
题意: 有一个1-n的全排列,m个询问,某个区间的整除对对数(1-1,2-4,1-2)
解析:
首先可以简单的得出下标1~i内的对数:枚举每个数的倍数,标记位置较大的那个,再做前缀和。
区间 的对数= 。现在就是处理这个之间的影响。
从小到大for,有一对 ,则树状数组 ,这个就是 的影响。那么 对 的影响就是 。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int sum[maxn];
int pos[maxn];
vector<int>R[maxn];
int tr[maxn];
void add(int p,int v,int n){
while(p<=n){
tr[p]+=v;
p+=p&-p;
}
}
int query(int p){
int res=0;
while(p){
res+=tr[p];
p-=p&-p;
}
return res;
}
struct node{
int l,r,id;
bool operator<(const node &R)const{
return l<R.l;
}
}e[maxn];
int sub[maxn];
int main(){
int n,m;scanf("%d%d",&n,&m);
for(int i=1,tmp;i<=n;i++)scanf("%d",&tmp),pos[tmp]=i;
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j+=i){
if(pos[j]){
int l=min(pos[i],pos[j]),r=max(pos[i],pos[j]);
R[l].push_back(r);
sum[r]++;
}
}
}
for(int i=1;i<=n;i++)sum[i]+=sum[i-1];
for(int i=1;i<=m;i++)scanf("%d%d",&e[i].l,&e[i].r),e[i].id=i;
sort(e+1,e+1+m);
int ar=1;
for(int i=1;i<=n;i++){
while(ar<=m&&e[ar].l==i)
sub[e[ar].id]=query(e[ar].r)-query(e[ar].l-1),++ar;
for(int j=0;j<R[i].size();j++)
add(R[i][j],1,n);
}
for(int i=1,l=e[1].l,r=e[1].r; i<=m; ++i,l=e[i].l,r=e[i].r)
sub[e[i].id]=sum[r]-sum[l-1]-sub[e[i].id];
for(int i=1;i<=m;i++)
printf("%d\n",sub[i]);
}