queryhtml
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).c++
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.spa
For each query, print a single line containing only one integer which denotes the number of pair(i,j)(i,j)..net
3 2 1 2 3 1 3 2 3
2 0
題意很好理解。就是二維偏序+樹狀數組。code
比賽時的隊友們的代碼寫的太醜,學了一下別人的代碼,寫的很好。htm
參考連接:query(2019徐州網絡賽)(一點思惟+樹狀數組)blog
代碼:ip
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\n",ans[i]); 64 } 65 return 0; 66 }