Codeforces Round #182 (Div. 1)--D. Yaroslav and Divisors--树状数组

D. Yaroslav and Divisors

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Yaroslav has an array p = p1, p2, ..., pn (1 ≤ pi ≤ n), consisting of n distinct integers. Also, he has m queries:

  • Query number i is represented as a pair of integers liri (1 ≤ li ≤ ri ≤ n).
  • The answer to the query li, ri is the number of pairs of integers qw (li ≤ q, w ≤ ri) such that pq is the divisor of pw.

Help Yaroslav, answer all his queries.

Input

The first line contains the integers n and m (1 ≤ n, m ≤ 2·105). The second line contains n distinct integers p1, p2, ..., pn(1 ≤ pi ≤ n). The following m lines contain Yaroslav's queries. The i-th line contains integers li, ri (1 ≤ li ≤ ri ≤ n).

Output

Print m integers — the answers to Yaroslav's queries in the order they appear in the input.

Please, do not use the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams or the %I64d specifier.

Examples

input

Copy

1 1
1
1 1

output

Copy

1

input

Copy

10 9
1 2 3 4 5 6 7 8 9 10
1 10
2 9
3 8
4 7
5 6
2 2
9 10
5 10
4 10

output

Copy

27
14
8
4
2
1
2
7
9
2
4 6
1 2
1 3
1 4
2 3
2 4
3 4
6 8
2 5
5 4
4 3
4 1
1 3
2 3
2 6
5 6

output

Copy

2
1 3
3
4 3 6

Note

In the first query any vertex or any pair of vertices will suffice.

Note that you don't have to minimize the number of chosen vertices. In the second query two vertices can be enough (vertices 22 and 44) but three is also ok.

 

给出一个图,求分成两部分,使得两部分联通。

其中选择的那一部分<=n/2,求选择的那一部分的点的个数及点的标号。

bfs整个图形,dis为奇数的和dis为奇数的就自动分成了两部分,且这两部分的最小值肯定不会超过n/2,所以选择奇数或偶数的最小值输出即可。bfs很好的一个性质。

 

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#define ll long long

using namespace std;

const int N = 2e5+100;



struct Node {
    int l,r,id;

} q[N];
bool cmp(Node aa,Node bb){
	return aa.l<bb.l;
}
long long myPre[N],sum[N],ans[N];;
int a[N],mark[N],myPos[N];

void myAdd(int x) {
    for(; x<N; x+=x&-x)sum[x]++;
}
int que(int x) {
    long long ans=0;
    for(; x; x-=x&-x)ans+=sum[x];
    return ans;
}
void sol1(int n,int m,int tot) {
	for(int i=0;i<=n;i++)myPre[i]=0;
    myPre[n]=tot;
    for(int i=n; i>=2; i--) {
        myPre[i-1]=myPre[i];
        for(int j=1; j*j<=a[i]; j++) {
            if(a[i]%j==0) {
                if(!mark[j])myPre[i-1]--;
                if(a[i]/j!=j&&!mark[a[i]/j])myPre[i-1]--;
            }
        }
        for(int j=2; j*a[i]<=n; j++) if(!mark[a[i]*j])myPre[i-1]--;
        mark[a[i]]=1;
    }
}
void sol2(int n,int m) {
    memset(mark,0,sizeof(mark));
    for(int i=1; i<=m; i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
    int p=1;
    sort(q+1,q+1+m,cmp);
    for(int i=1; i<=m; i++) {
        while(p<q[i].l) {
            for(int j=1; j*j<=a[p]; j++) {
                if(a[p]%j==0) {
                    if(!mark[j])myAdd(myPos[j]);
                    if(a[p]/j!=j&&!mark[a[p]/j])myAdd(myPos[a[p]/j]);
                }
            }
            for(int j=2; j*a[p]<=n; j++) {
                if(!mark[a[p]*j])myAdd(myPos[a[p]*j]);
            }
            mark[a[p]]=1;
            p++;
        }
        ans[q[i].id]=myPre[q[i].r]-myPre[q[i].l-1]-que(q[i].r)+que(q[i].l-1);
    }
}
int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    long long tot=n;
    for(int i=1; i<=n; i++) {
        scanf("%d",&a[i]),myPos[a[i]]=i;
        tot=tot+n/i-1;
    }
    sol1(n,m,tot);
    sol2(n,m);
    for(int i=1; i<=m; i++)
        printf("%lld\n",ans[i]);
    return 0;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值