您的位置:首页 > 其它

Codeforce 301D - Yaroslav and Divisors

2013-05-16 13:30 260 查看
确定了没有方便的更新统计方法,就想是不是要一个一个更新,

考虑(n/2 + n/3 + n/4 ..... n/n)其实不大,(1/2 + 1/3 + ....1/200000) <13

所以暴力之

更新时没问题,但直接统计个数会超时,要用到logn的东西

影响最终结果有两个因素: 1-n摆放的顺序和倍数;

数据结构中经典的解决两个因素制约的方法是先保存查询,然后边 插入边查询

设想一个查询 [L,R],当插入到L-1时,这时[1,L-1]之间的数的倍数已经处理完了,算出的是[1,L-1]之间的数对[L,R]的影响

当插入到R之后,这时[1,R]之间的数的倍数已经处理完了,算出的是[1,R]之间的数对[L,R]的影响

前后结果相减,消除掉[1,L-1]之间的数的影响,结果就出来了

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <vector>

using namespace std;

#define N 200500

int a
,p
,b
,l
,r
,ans
;

vector<int>ll
,rr
;

int n,m;

inline int lowbit(int x)

{

return x&(-x);

}

void update(int x)

{

while(x<=n)

{

b[x]++;

x+=lowbit(x);

}

}

int query(int x)

{

int res=0;

while(x>=1)

{

res+=b[x];

x-=lowbit(x);

}

return res;

}

int main ()

{

scanf("%d%d",&n,&m);

for(int i=1;i<=n;++i)

{

scanf("%d",&a[i]);

p[a[i]]=i;

}

for(int i=1;i<=m;++i)

{

scanf("%d%d",&l[i],&r[i]);

ll[l[i]].push_back(i);

rr[r[i]].push_back(i);

}

for(int i=1;i<=n;++i)

{

for(int j=0;j<ll[i].size();++j)

ans[ll[i][j]]-=query(r[ll[i][j]])-query(i-1);

for(int j=1;j*a[i]<=n;++j)

update(p[j*a[i]]);

for(int j=0;j<rr[i].size();++j)

ans[rr[i][j]]+=query(i)-query(l[rr[i][j]]-1);

}

for(int i=1;i<=m;++i)

printf("%d\n",ans[i]);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: