计蒜客 41391.query-二维偏序+树状数组(预处理出来满足情况的gcd) (The Preliminary Contest for ICPC Asia Xuzhou 2019 I.) 2019年徐州网络赛)

query

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 rli<jr 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(1n105), m(1 \le m \le 10^5)m(1m105) 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(1lirin), 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\n",ans[i]);
64     }
65     return 0;
66 }

猜你喜欢

转载自www.cnblogs.com/ZERO-/p/11488127.html