zoukankan      html  css  js  c++  java
  • Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)

    题目链接:http://codeforces.com/contest/474/problem/F

    题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数就是答案。

    要是符合条件的话,那这个数的大小一定是等于gcd(a[l]...a[r])。

    我们求区间gcd的话,既可以利用线段树性质区间递归下去然后返回求解,但是每次查询是log的,所以还可以用RMQ,查询就变成O(1)了。

    然后求解区间内有多少个数的大小等于gcd的话,也是利用线段树的性质,区间递归求解之,复杂度也是log的。

     1 //#pragma comment(linker, "/STACK:102400000, 102400000")
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <ctime>
    10 #include <list>
    11 #include <set>
    12 #include <map>
    13 using namespace std;
    14 typedef long long LL;
    15 typedef pair <int, int> P;
    16 const int N = 1e5 + 5;
    17 int gcd[N][20];
    18 struct SegTree {
    19     int l , r , Min , num;
    20 }T[N << 3];
    21 
    22 int GCD(int a, int b) {
    23     return b ? GCD(b, a % b) : a;
    24 }
    25 
    26 void ST(int n) {
    27     for(int k = 1; k < 20; ++k) {
    28         for(int i = 1; i + (1 << k) - 1 <= n; ++i) {
    29             gcd[i][k] = GCD(gcd[i][k - 1], gcd[i + (1 << (k - 1))][k - 1]);
    30         }
    31     }
    32 }
    33 
    34 void build(int p , int l , int r) {
    35     int mid = (l + r) >> 1;
    36     T[p].l = l , T[p].r = r , T[p].num;
    37     if(l == r) {
    38         T[p].Min = gcd[l][0];
    39         T[p].num = 1;
    40         return ;
    41     }
    42     build(p << 1 , l , mid);
    43     build((p << 1)|1 , mid + 1 , r);
    44     if(T[p << 1].Min == T[(p << 1)|1].Min) {
    45          T[p].Min = T[p << 1].Min;
    46          T[p].num = T[p << 1].num + T[(p << 1)|1].num;
    47     }
    48     else if(T[p << 1].Min < T[(p << 1)|1].Min) {
    49         T[p].Min = T[p << 1].Min;
    50         T[p].num = T[p << 1].num;
    51     }
    52     else {
    53         T[p].Min = T[(p << 1)|1].Min;
    54         T[p].num = T[(p << 1)|1].num;
    55     }
    56 }
    57 
    58 int query(int p , int l , int r , int g) {
    59     int mid = (T[p].l + T[p].r) >> 1;
    60     if(T[p].l == l && T[p].r == r) {
    61         return T[p].Min == g ? T[p].num : 0;
    62     }
    63     if(r <= mid) {
    64         return query(p << 1 , l , r , g);
    65     }
    66     else if(l > mid) {
    67         return query((p << 1)|1 , l , r , g);
    68     }
    69     else {
    70         return query(p << 1 , l , mid , g) + query((p << 1)|1 , mid + 1 , r , g);
    71     }
    72 }
    73 
    74 int main()
    75 {
    76     int n, q, l, r;
    77     scanf("%d", &n);
    78     for(int i = 1; i <= n; ++i)
    79         scanf("%d", &gcd[i][0]);
    80     ST(n);
    81     build(1 , 1 , n);
    82     scanf("%d", &q);
    83     while(q--) {
    84         scanf("%d %d", &l, &r);
    85         int k = log2(r - l + 1);
    86         int g = GCD(gcd[l][k], gcd[r - (1 << k) + 1][k]);
    87         printf("%d
    ", r - l + 1 - query(1 , l , r , g));
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    给X轴添加滚动条,放大X轴Y轴
    win7下发布网站
    asp.net播放声音
    用Flash方式动态生成图表
    debian programming guid
    php 自动跳转的3种方法
    用expect实现su c功能,身份切换
    11 Top Opensource Resources for Cloud Computing
    转:Linux系统下Shell命令行快捷键实用技巧
    sed 替换
  • 原文地址:https://www.cnblogs.com/Recoder/p/5711993.html
Copyright © 2011-2022 走看看