zoukankan      html  css  js  c++  java
  • codeforces 301D 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.

    题目大意:给一个1~n的排列,有m个询问,问L到R之间有多少对数满足一个数是另一个数的约数。

    思路:果然数学才是王道……

    1~n个数,满足一个数是另一个数的约数的数对,一共有n/1 + n/2 + …… + n/n ≈ nlogn个(大概吧其实我也不会算),也就是32位够了

    然后怎么计算L到R有多少对呢?本来想的是用1~R的对数减去1~L-1的对数,结果发现这样算的结果包含了一个属于1~L-1另一个属于L~R的合法对。

    于是进一步思考,令x = 1~R的对数减去1~L-1的对数,y = 一个属于1~L-1另一个属于L~R的合法对数,答案ans = x - y。

    这个好像没有办法在短时间内在线处理出来,于是采用离线处理。

    i从1到n循环,对所有的query.L=i,减去sum[R] - sum[L-1],即上面所说的y(此时L~R的合法对还没被计算出来)。然后找出所有i的倍数,加到sum里面。再对所有的query.R=i,加上sum[R] - sum[L-1],即上面所说的x(此时L~R的合法对已经计算出来了)。

    对于这种需要单点更新,区间求值的操作,树状数组可以满足你。

    代码(498MS):

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int MAXN = 200010;
     8 
     9 int a[MAXN], pos[MAXN], tree[MAXN];
    10 int n, m;
    11 
    12 int lowbit(int x) {
    13     return x & (-x);
    14 }
    15 
    16 int get_sum(int k) {
    17     int ans = 0;
    18     while(k > 0) {
    19         ans += tree[k];
    20         k -= lowbit(k);
    21     }
    22     return ans;
    23 }
    24 
    25 void modify(int k, int val) {
    26     while(k <= n) {
    27         tree[k] += val;
    28         k += lowbit(k);
    29     }
    30 }
    31 
    32 struct QUERY {
    33     int id, L, R;
    34     bool operator < (const QUERY &rhs) const {
    35         return L < rhs.L;
    36     }
    37 } query[MAXN], query_t[MAXN];
    38 
    39 int ans[MAXN];
    40 
    41 int main() {
    42     scanf("%d%d", &n, &m);
    43     for(int i = 1; i <= n; ++i) {
    44         scanf("%d", &a[i]);
    45         pos[a[i]] = i;
    46     }
    47     for(int i = 1; i <= m; ++i) {
    48         scanf("%d%d", &query[i].L, &query[i].R);
    49         query_t[i].L = query[i].R;
    50         query_t[i].R = query[i].L;
    51         query[i].id = query_t[i].id = i;
    52     }
    53     sort(query + 1, query + m + 1);
    54     sort(query_t + 1, query_t + m + 1);
    55     for(int i = 1, j = 1, k = 1; i <= n; ++i) {
    56         while(j <= m && query[j].L == i) {
    57             ans[query[j].id] -= get_sum(query[j].R) - get_sum(query[j].L - 1);
    58             ++j;
    59         }
    60         for(int p = a[i]; p <= n; p += a[i]) modify(pos[p], 1);
    61         while(k <= m && query_t[k].L == i) {
    62             ans[query_t[k].id] += get_sum(query_t[k].L) - get_sum(query_t[k].R - 1);
    63             ++k;
    64         }
    65     }
    66     for(int i = 1; i <= m; ++i) printf("%d
    ", ans[i]);
    67 }
    View Code
  • 相关阅读:
    input清楚阴影 number属性
    转 溢出隐藏
    多行,溢出隐藏 css
    JS判断移动端还是PC端(改造自腾讯网) 仅用于宣传动画,下载页等
    项目开发(Require + E.js)
    showPrompt弹框提示
    图形验证码
    CSS常用技术总结!~~
    移动开发常用技术总结!~~
    JavaScript常用技术总结!~~
  • 原文地址:https://www.cnblogs.com/oyking/p/3256922.html
Copyright © 2011-2022 走看看