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
题意很好理解。就是二维偏序+树状数组。
比赛时的队友们的代码写的太丑,学了一下别人的代码,写的很好。
参考链接:query(2019徐州网络赛)(一点思维+树状数组)
代码:
1 //I.二维偏序+树状数组 2 //提前预处理出来所有的倍数关系,然后按顺序,先插入然后查询 3 #include<bits/stdc++.h> 4 using namespace std; 5 typedef long long ll; 6 #define pb push_back 7 #define mp make_pair 8 #define pii pair<int,int> 9 const int maxn=1e5+10; 10 11 int a[maxn],pos[maxn],tree[maxn],ans[maxn]; 12 int n,m; 13 vector<int> gcd[maxn]; 14 vector<pii> op[maxn]; 15 16 int lowbit(int x) 17 { 18 return x&(-x); 19 } 20 21 void add(int x,int val) 22 { 23 for(int i=x;i<=n;i+=lowbit(i)){ 24 tree[i]+=val; 25 } 26 } 27 28 int query(int n) 29 { 30 int ans=0; 31 for(int i=n;i>0;i-=lowbit(i)){ 32 ans+=tree[i]; 33 } 34 return ans; 35 } 36 37 int main() 38 { 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=n;i++){ 41 scanf("%d",&a[i]); 42 pos[a[i]]=i;//记录下标 43 } 44 for(int i=1;i<=n;i++){ 45 for(int j=a[i]*2;j<=n;j+=a[i]){ 46 gcd[max(i,pos[j])].pb(min(i,pos[j]));//预处理 47 } 48 } 49 for(int i=1;i<=m;i++){ 50 int l,r; 51 scanf("%d%d",&l,&r); 52 op[r].pb(mp(l,i));//保存查询 53 } 54 for(int i=1;i<=n;i++){ 55 for(auto it:gcd[i]){ 56 add(it,1);//先把插入 57 } 58 for(auto it:op[i]){ 59 ans[it.second]=query(i)-query(it.first-1);//查询 60 } 61 } 62 for(int i=1;i<=m;i++){ 63 printf("%d ",ans[i]); 64 } 65 return 0; 66 }