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 li, ri (1 ≤ li ≤ ri ≤ n).
- The answer to the query li, ri is the number of pairs of integers q, w (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;