您的位置:首页 > 其它

codeforces 301D. Yaroslav and Divisors(遍历和排序的艺术)

2015-12-23 23:53 399 查看
http://codeforces.com/problemset/problem/301/D

大意:给定一串数字,然后有m个询问,每一个询问问从l到r一共有多少对整除关系?

一个数i的在1——n内的倍数的个数是 n/i

那么,1-i的倍数个数有: f(1,i)=n/1+n/2+n/3+……+n/i

1-i在k内的倍数个数有:g(1,i,k)=k/1+k/2+k/3+……+k/i

L-R的倍数情况是: g(l,r,k)=g(1,r,k)-g(1,l,k)

我们要求的东西: g(l,r,r)=g(1,r,r)-g(1,l,r);

如果 原始数组是 1,2,3,……,n是极好的,但不是。。。

矛盾用1-n的主遍历解决(我承认一开始我没想到,学习了别人的博文才知道的):

设que1是L从小到大排过序的, que2是R从从小到大排过序的。(数组排序的艺术,遍历的艺术)

当que1[iterator].l==i 有ans[que1[iterator].pos]]-=(
sum(que1[iterator].right))-sum(que1[iterator].left))
当que2[iterator].r==i 有ans[que2[iterator].pos]]+=(
sum(que1[iterator].right))-sum(que1[iterator].left))
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=2e5+10;
int c
,a
;
int n,m;
int lowbit(int k){
return k&(k^(k-1));
}
void update(int dex,int k){
while(dex<=n){
c[dex]+=k;
dex+=lowbit(dex);
}
}
int sum(int k){
int ans=0;
while(k>0){
ans+=c[k];
k=k-lowbit(k);
}
return ans;
}
struct node {
int l,r,dex;
}que1
,que2
;
int cmp1(node k,node b){
return k.l<b.l;
}
int cmp2(node k,node b){
return k.r<b.r;
}
int ans
,pos
;
int main()
{
//freopen("cin.txt","r",stdin);
while(cin>>n>>m){
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&que1[i].l,&que1[i].r);
que1[i].dex=i;
que2[i].l=que1[i].l;
que2[i].r=que1[i].r;
que2[i].dex=i;
}
sort(que1+1,que1+m+1,cmp1);
sort(que2+1,que2+m+1,cmp2);
for(int i=1,j=1,k=1;i<=n;i++){
while(j<=m&&que1[j].l==i){
ans[que1[j].dex]-=(sum(que1[j].r)-sum(que1[j].l-1));
j++;
}
for(int p=a[i];p<=n;p+=a[i]){
update(pos[p],1);
}
while(k<=m&&que2[k].r==i){
ans[que2[k].dex]+=(sum(que2[k].r)-sum(que2[k].l-1));
k++;
}
}
for(int i=1;i<=m;i++){
printf("%d\n",ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: