Codeforces Round #182 (Div. 1) Yaroslav and Divisors(離線+樹狀數組)

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 liri (1 ≤ li ≤ ri ≤ n).
  • The answer to the query li, ri is the number of pairs of integers qw (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 cincout streams or the %I64dspecifier.

Examples
input
1 1
1
1 1
output
1
input
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
27
14
8
4
2
1
2
7
9


分析:注意非常重要的一點就是整個數列是一個排列,這樣對於一個1到n的排列成倍數關係的數其實是非常少的,大概是nlogn這個數量級,所以我們先把所有成倍關係的兩元組求出來,這樣設其中下標較大的下標爲x,較小的爲y,那麼問題就轉化爲了每次求一段區間l到r中包含的成對的[x,y]的個數,這個問題有一個經典的離線做法,從左向右掃描序列,每次把小於當前位置i的y對應的x更新到樹狀數組裏邊,那麼對於r = i的詢問,其答案就是sum(r) - sum(l-1).
#include<bits/stdc++.h>
#define N 200005
using namespace std;
typedef pair<int,int> pii;
vector<int> G[N];
vector<pii> ask[N];
int n,m,x,p[N],f[N],ans[N];
void Insert(int x)
{
    int p = x;
    while(p <= n)
    {
        f[p]++;
        p += p & (-p);
    }
}
int Sum(int x)
{
    int p = x,ans = 0;
    while(p)
    {
        ans += f[p];
        p -= p & (-p);
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&x);
        p[x] = i;
    }
    for(int i = 1;i <= n;i++)
     for(int j = i;j <= n;j+=i)
     {
        int x = p[i],y = p[j];
        if(x > y) swap(x,y);
        G[y].push_back(x);
     }
    for(int i = 1;i <= m;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        ask[r].push_back(make_pair(l,i));
    }
    for(int i = 1;i <= n;i++)
    {
        for(int v : G[i]) Insert(v);
        for(pii v : ask[i]) ans[v.second] = Sum(i) - Sum(v.first-1);
    }
    for(int i = 1;i <= m;i++) cout<<ans[i]<<endl;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章