Given a permutation pp of length nn, you are asked to answer mm queries, each query can be represented as a pair (l ,r )(l,r), you need to find the number of pair(i ,j)(i,j) such that l \le i < j \le rl≤i<j≤r and \min(p_i,p_j) = \gcd(p_i,p_j )min(pi,pj)=gcd(pi,pj).
Input
There is two integers n(1 \le n \le 10^5)n(1≤n≤105), m(1 \le m \le 10^5)m(1≤m≤105) in the first line, denoting the length of pp and the number of queries.
In the second line, there is a permutation of length nn, denoting the given permutation pp. It is guaranteed that pp is a permutation of length nn.
For the next mm lines, each line contains two integer l_ili and r_i(1 \le l_i \le r_i \le n)ri(1≤li≤ri≤n), denoting each query.
Output
For each query, print a single line containing only one integer which denotes the number of pair(i,j)(i,j).
样例输入复制
3 2
1 2 3
1 3
2 3
样例输出复制
2
0
萌新终于学习到二维偏序这类题目的一些做法了。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn=100010;
int id[maxn];
struct L
{
int x,y;
}line[20*maxn];//要多开10倍
struct Q
{
int l,r;
int ind;
}q[maxn];
int a[maxn];
bool cmp1(L i,L j)
{
return i.y<j.y;//按照y排序
}
bool cmp2(Q i,Q j)
{
return i.r<j.r;//按照r排序
}
struct node
{
int l,r;
int va;
}tree[maxn<<2];
void pushup(int rt)
{
tree[rt].va=tree[rt<<1].va+tree[rt<<1|1].va;
}
void build(int rt,int l,int r)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].va=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void update(int rt,int p,int v)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].va+=v;
return;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(mid>=p) update(rt<<1,p,v);
else update(rt<<1|1,p,v);
pushup(rt);
}
int query(int rt,int L,int R)
{
if(tree[rt].l>=L&&tree[rt].r<=R)
{
return tree[rt].va;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
int ans=0;
if(mid>=L) ans+=query(rt<<1,L,R);
if(mid<R) ans+=query(rt<<1|1,L,R);
return ans;
}
int res[maxn];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
id[a[i]]=i;
}
int tot=0;
for(int i=1;i<=n;i++)
{
for(int j=i+i;j<=n;j+=i)
{
line[++tot].x=id[i];
line[tot].y=id[j];
if(id[i]>id[j])
{
swap(line[tot].x,line[tot].y);
}
}
}
for(int i=1;i<=m;i++)
{
scanf("%d %d",&q[i].l,&q[i].r);
q[i].ind=i;
}
sort(line+1,line+tot+1,cmp1);
sort(q+1,q+m+1,cmp2);
int cnt=1;
build(1,1,n);
for(int i=1;i<=m;i++)
{
while(cnt<=tot&&line[cnt].y<=q[i].r)
{
update(1,line[cnt].x,1);
cnt++;
}
res[q[i].ind]=query(1,q[i].l,q[i].r);
}
for(int i=1;i<=m;i++)
{
printf("%d\n",res[i]);
}
return 0;
}