• hdu 5317 RGCDQ(前缀和)


      题目链接:hdu 5317

      这题看数据量就知道需要先预处理,然后对每个询问都需要在 O(logn) 以下的复杂度求出,由数学规律可以推出 1 <= F(x) <= 7,所以对每组(L, R),只需要求出它们在 1~7 的范围内的数量,然后暴力求出 gcd 即可。因为符合递增,可以设一个结点 struct { v[8]; } 记录 1~7 的数量,结点间可以相加减,也就可以用前缀和的思想去做(其实我也是看了别人的题解才明白这种思想,一开始用二分不是超时就是 wa 了,不过我竟发现自己手写的二分比库函数 lower_bound 要快!而且至少快 7~8 倍以上!看来以后用二分都尽量自己手写好了 (ㄒoㄒ)~~ )

      先附上用前缀和的思想的代码,加入了输入输出挂:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N = 1000006;
     6 
     7 struct node {
     8     int v[8];
     9     node() {   memset(v,0,sizeof(v));   }
    10     node operator + (const node &n2) const {
    11         node add;
    12         for(int i = 1; i <= 7; ++i)
    13             add.v[i] = v[i] + n2.v[i];
    14         return add;
    15     }
    16     node operator - (const node &n2) const {
    17         node sub;
    18         for(int i = 1; i <= 7; ++i)
    19             sub.v[i] = v[i] - n2.v[i];
    20         return sub;
    21     }
    22     node& operator += (const node &n2) {
    23         *this = *this + n2;
    24         return *this;
    25     }
    26     node& operator -= (const node &n2) {
    27         return *this = *this - n2;
    28     }
    29 };
    30 
    31 int num[N];
    32 node _count[N];
    33 inline void init(int n = N - 3) {
    34     for(int i = 2; i <= n; ++i)
    35         if(!num[i])
    36         for(int j = i; j <= n; j += i)   ++num[j];
    37     for(int i = 2; i <= n; ++i) {
    38         node tmp;
    39         ++tmp.v[num[i]];
    40         _count[i] = _count[i - 1] + tmp;
    41     }
    42 }
    43 
    44 inline int gcd(int a, int b) {
    45     return b == 0 ? a: gcd(b, a % b);
    46 }
    47 
    48 #include<cctype>
    49 template <typename T>
    50 inline void read(T &x) {
    51     x = 0;
    52     char ch = getchar();
    53     bool flag = 0;
    54     while(!isdigit(ch) && ch != '-')   ch = getchar();
    55     if(ch == '-') {
    56         flag = 1;
    57         ch = getchar();
    58     }
    59     while(isdigit(ch)) {
    60         x = x * 10 + (ch - '0');
    61         ch = getchar();
    62     }
    63     if(flag)    x = -x;
    64 }
    65 
    66 template <typename T>
    67 inline void write(const T &x) {
    68     if(x < 10)   putchar(char(x + '0'));
    69     else    write(x / 10);
    70 }
    71 
    72 int main() {
    73     int t,L,R;
    74     init();
    75     read(t);
    76     while(t--) {
    77         read(L);    read(R);
    78         node p = _count[R] - _count[L - 1];
    79         int ans = 0;
    80         for(int i = 1; i <= 7; ++i) {
    81             if(!p.v[i])   continue;
    82             --p.v[i];
    83             for(int j = i; j <= 7; ++j)
    84                 if(p.v[j])    ans = max(ans, gcd(i,j));
    85             ++p.v[i];
    86         }
    87         write(ans);
    88         puts("");
    89     }
    90     return 0;
    91 }
    View Code

      说到前缀和,就可以联想起高效动态维护前缀和的树状数组。没错,只要能求前缀和的数据结构,都能用树状数组去维护,它的适用范围不只是简单的 int,long long 或者 一维数组(二维树状数组去维护)等等。因此我定义成模板类:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cctype>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N = 1000006;
     7 
     8 struct node {
     9     int v[8];
    10     void clear()  {   memset(v,0,sizeof(v));   }
    11     node()  {   clear();   }
    12     node operator + (const node &n2) const {
    13         node add;
    14         for(int i = 1; i <= 7; ++i)
    15             add.v[i] = v[i] + n2.v[i];
    16         return add;
    17     }
    18     node operator - (const node &n2) const {
    19         node sub;
    20         for(int i = 1; i <= 7; ++i)
    21             sub.v[i] = v[i] - n2.v[i];
    22         return sub;
    23     }
    24 };
    25 
    26 #define  lowbit(x)  ((x)&-(x))
    27 template <typename T>
    28 struct tree {
    29     T c[N];
    30     int maxn;
    31     void clear() {      // 或者直接 memset(c, 0, sizeof(c)) 也可以;
    32         for(int i = 0; i <= maxn; ++i)
    33             c[i].clear();
    34     }
    35     tree(int maxn = N - 3): maxn(maxn)  {   clear();   }
    36     T sum(int x) const {
    37         T res;
    38         while(x) {
    39             res = res + c[x];
    40             x -= lowbit(x);
    41         }
    42         return res;
    43     }
    44     void add(int x, T d) {
    45         while(x <= maxn) {
    46             c[x] = c[x] + d;
    47             x += lowbit(x);
    48         }
    49     }
    50 };
    51 
    52 tree<node> tr;
    53 
    54 int num[N];
    55 void init(int n = N - 3) {
    56     for(int i = 2; i <= n; ++i)
    57         if(!num[i])
    58         for(int j = i; j <= n; j += i)  ++num[j];
    59     for(int i = 2; i <= n; ++i) {
    60         node tmp;
    61         ++tmp.v[num[i]];
    62         tr.add(i, tmp);
    63     }
    64 }
    65 
    66 inline int gcd(int a, int b) {
    67     return b == 0 ? a: gcd(b, a % b);
    68 }
    69 
    70 int main() {
    71     int t,L,R;
    72     init();
    73     scanf("%d",&t);
    74     while(t--) {
    75         scanf("%d %d",&L,&R);
    76         node p = tr.sum(R) - tr.sum(L - 1);
    77         int ans = 0;
    78         for(int i = 1; i <= 7; ++i) {
    79             if(!p.v[i])   continue;
    80             --p.v[i];
    81             for(int j = i; j <= 7; ++j)
    82                 if(p.v[j])   ans = max(ans, gcd(i, j));
    83             ++p.v[i];
    84         }
    85         printf("%d
    ",ans);
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    cmd常用命令
    SqlServer 、MySQL查询库中表明 字段信息
    每科成绩大于80分 查询 删除重复记录
    1
    go语言体系学习(一):环境准备与变量
    PriorityQueue及二叉堆
    LinkedList的几个元素操作方法
    判定字符是否唯一的面试题想到
    python爬虫利器 scrapy和scrapy-redis 详解一 入门demo及内容解析
    mongodb 数据操作CRUD
  • 原文地址:https://www.cnblogs.com/Newdawn/p/4691817.html
Copyright © 2020-2023  润新知