• query 线段树 + 区间排序


    https://nanti.jisuanke.com/t/41391

    这个题目没有很难想,比较暴力,但是要会算复杂度,不会算复杂度,就会觉得自己的算法会超时,实际上不会。

    这个题目就是直接暴力求出每一个数的在1e5以内的所有的约数和倍数,然后更新,就像之前写过的E - No Pain No Game 线段树 离线处理 区间排序 一样

    算一下复杂度,调和级数要用两次,一次来求约数一次来求倍数,复杂度都是n*logn 所以平均下来每一个的约数大约就是logn 

    因为有个两倍的关系所以就是2*logn

    线段树的复杂度,每次更新是logn ,要遍历一次

    所以总的复杂度就是2*n*logn*logn,这个肯定不会超时的。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    #include <iostream>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 10;
    typedef long long ll;
    vector<int>num[maxn];
    int a[maxn], vis[maxn], c[maxn], ans[maxn];
    int n, m;
    struct node
    {
        int l, r, id;
        node(int l=0,int r=0,int id=0):l(l),r(r),id(id){}
    }ex[maxn];
    bool cmp(node a,node b)
    {
        return a.r < b.r;
    }
    
    int lowbit(int x)
    {
        return x & (-x);
    }
    
    void update(int x,int k)
    {
        while (x <= n) {
            c[x] += k;
            x += lowbit(x);
        }
    }
    
    int getsum(int x)
    {
        int ans = 0;
        while (x > 0) {
            ans += c[x];
            x -= lowbit(x);
        }
        return ans;
    }
    
    int main()
    {
        for (int i = 1; i < maxn; ++i) {
            for (int j = 2*i; j < maxn; j += i) {
                num[j].push_back(i);//先把每个数的因子有哪些打个表,由调和级数可知复杂度为o(nlog n)
            }
        }
        for (int i = 1; i < maxn; ++i) {
            for (int j = 2 * i; j < maxn; j += i) {
                num[i].push_back(j);
            }
        }
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for (int i = 1; i <= m; i++) {
            int l, r;
            scanf("%d%d", &l, &r);
            ex[i] = node(l, r, i);
        }
        memset(vis, -1, sizeof(vis));
        sort(ex + 1, ex + 1 + m, cmp);
        int now = 1;
        for (int i = 1; i <= n; i++) {
            int x = a[i];
            for (int j = 0; j < num[x].size(); j++) {
                int y = num[x][j];
                if (vis[y] != -1) update(vis[y], 1);
            }
            vis[x] = i;
            while (now <= m && i == ex[now].r) {
                int res = getsum(ex[now].r) - getsum(ex[now].l - 1);
                ans[ex[now].id] = res;
                now++;
            }
        }
        for (int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    【转载】 K2 blackpearl 中的业务规则(Rules)
    【转载】工作流模式与K2实现(2)
    7.10学习内容。 J
    第三章 J
    C博客作业01分支、顺序结构
    C语言博客作业循环结构
    我的C语言第一篇博客!
    使用NDK创建及配置C++程序(原生纯C++项目,不包含JAVA代码)
    关于工作中的错误
    【博文翻译】Building Boost with NDK R5
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11521242.html
Copyright © 2020-2023  润新知