zoukankan      html  css  js  c++  java
  • CodeForces

    一道通过预处理使得无需使用lower_bound的题,最终的复杂度是O(MlogN),也算是对调和复杂度分析的一个练习吧

    题意:给定不超过n(1<=n<=200000)个数,每个数介于1~1e6之间,选定两个数使得ai%aj最大

    思路:对于一个值aj,我们要找到ai使ans=ai%aj最大,ans显然小于aj。我们希望ans越大,就要求ai越靠近且略小于aj的倍数。由于给出的数列的值是有上界的,我们对于从[aj, aj + aj)开始的每段区间长度为aj的段,找出那个最大的数,然后更新ans的值即可。问题在于如何找到那个最大的数?第一反应可能会想到先对数组进行排序,然后再利用lower_bound进行二分搜索。这样以来复杂度是(NlogN + MlogMlogN),可不可以卡过没有尝试过。

      但是重点在与,我们对于每个不大于2*上界的值,我们可以预处理出给定的数列里不大于它的最大值,这个过程只需要O(M)就可以实现了,这样以来,查询过程的复杂度就是O(1),总的复杂度就是O(MlogN)了,强无敌啊。

      我开了两个数组,pre[i]用于记录题目给定数列中小于i的最大值,a[i]用于记录i是否在原数列中出现过。枚举所有值不同的aj,去更新ans。最多N个aj,每个在第二层循环运行(2 * 上界 / aj) - 1次,那就约为一个上界*调和级数的复杂度。最坏情况下,(1+1/2+1/3+...+1/N),调和级数的值为log(N) + C(欧拉常数),所以总的复杂度是O(MlogN)

     1 #include <queue>
     2 #include <vector>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <iostream>
     6 #include <algorithm>
     7 #define INF 0x3f3f3f3f
     8 #define MOD 1000000007
     9 using namespace std;
    10 typedef long long LL;
    11 
    12 const int maxm = 1e6;
    13 int pre[maxm * 2 + 10];
    14 bool a[maxm + 10];
    15 int N;
    16 
    17 
    18 int main(int argc, const char * argv[]) {
    19     scanf("%d", &N);
    20     for (int i = 1; i <= N; i++) {
    21         int val;
    22         scanf("%d", &val);
    23         pre[val] = -1;
    24         a[val] = true;
    25     }
    26     //预处理
    27     int small = 0;
    28     int big = small;
    29     while (big <= maxm * 2) {
    30         while (big <= maxm * 2 && pre[big] != -1) {
    31             big++;
    32         }
    33         for (int i = small + 1; i <= big; i++) {
    34             pre[i] = small;
    35         }
    36         small = big;
    37     }
    38     
    39     int ans = 0;
    40     for (int i = 1; i <= maxm; i++) {
    41         if (!a[i]) continue;
    42         for (int j = i + i; j <= maxm * 2; j += i) {
    43             ans = max(ans, pre[j] % i);
    44         }
    45     }
    46     printf("%d
    ", ans);
    47     return 0;
    48 }
    View Code
  • 相关阅读:
    派生选择器
    HTML 标签
    $.get()
    CC150
    CC150
    CC150
    CC150
    HashMap和HashTable的区别
    CC150
    quickSort
  • 原文地址:https://www.cnblogs.com/xFANx/p/7324712.html
Copyright © 2011-2022 走看看