zoukankan      html  css  js  c++  java
  • hdu4777-Rabbit Kingdom

    题意:求区间内与其他任何数都互质的数的个数。

    题解:求出每个数左右互质的边界。然后对询问排序,通过树状数组求解。

    讲道理真的好难啊= =

    http://blog.csdn.net/dyx404514/article/details/15507209 这个博客讲的最清楚(竟然是戴神的博客=。= 听过戴神讲splay,现在还不会……

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 200005;
    
    /***素数打表***/
    int p[N];
    int is_p[N+1];
    int cnt_p;
    void get_p() {
        for (int i = 0; i <= N; ++i) is_p[i] = 1;
        cnt_p = is_p[0] = is_p[1] = 0;
        for (int i = 2; i <= N; ++i) {
            if (is_p[i]) {
                p[cnt_p++] = i;
                for (int j = i * 2; j <= N; j += i) is_p[j] = 0;
            }
        }
    }
    /***因数分解***/
    int fac[N];     // 记录出现的因数
    int cal_fac(int x) {
        int tmp = x;
        int idx = 0;
        int i;
        for (i = 0; p[i] <= tmp/p[i]; ++i) {
            if (tmp%p[i]) continue;
            while (tmp%p[i] == 0) tmp /= p[i];
            fac[idx++] = p[i];
        }
        if (tmp != 1) fac[idx++] = tmp;
        return idx;
    }
    /***计算每个数互质的最左最右区间***/
    int l[N], r[N];
    int adj[N];
    int a[N];
    void cal_inv(int n) {
        for (int i = 0; i < N; ++i) adj[i] = 0;
        for (int i = 1; i <= n; ++i) {
            int cnt = cal_fac(a[i]);
            l[i] = 0;
            for (int j = 0; j < cnt; ++j) {
                l[i] = max(l[i], adj[fac[j]]);
                adj[fac[j]] = i;
            }
        }
        for (int i = 0; i < N; ++i) adj[i] = n+1;
        for (int i = n; i >= 1; --i) {
            r[i] = n+1;
            int cnt = cal_fac(a[i]);
            for (int j = 0; j < cnt; ++j) {
                r[i] = min(r[i], adj[fac[j]]);
                adj[fac[j]] = i;
            }
        }
    }
    
    struct node {
        int l, r, id;
        bool operator<(const node x) const { return l < x.l; }
    } qry[N];
    
    int bit[N];
    int lowbit(int x) { return x&-x; }
    void add(int x, int v, int n) { while(x<=n) bit[x]+=v,x+=lowbit(x); }
    int sum(int x) { int ans=0; while(x) ans+=bit[x],x-=lowbit(x); return ans; }
    
    vector<int> lb[N]; // lb[i] 以i为左边界的数
    int ans[N];
    int main() {
    //freopen("in.txt", "r", stdin);
        get_p();
        int n, k;
        while (~scanf("%d%d", &n, &k)) {
            if (n == 0) break;
            for (int i = 1; i <= n; ++i) {
                scanf("%d", a+i);
            }
            cal_inv(n);
    
            for (int i = 0; i < k; ++i) {
                scanf("%d%d", &qry[i].l, &qry[i].r);
                qry[i].id = i;
            }
            sort(qry, qry+k);
            for (int i = 0; i <= n; ++i) lb[i].clear();
            memset(bit, 0, sizeof bit);
            for (int i = 1; i <= n; ++i) {
                if (!l[i]) { add(i, 1, n); add(r[i], -1, n); }
                else lb[l[i]].push_back(i);
            }
            int pos = 1;
            for (int i = 0; i < k; ++i) {
                while (qry[i].l > pos) {
                    add(pos, -1, n);
                    add(r[pos], 1, n);
                    for (unsigned j = 0; j < lb[pos].size(); ++j) {
                        int x = lb[pos][j];
                        add(x, 1, n);
                        add(r[x], -1, n);
                    }
                    pos++;
                }
                ans[qry[i].id] = sum(qry[i].r)-sum(qry[i].l-1);
            }
            for (int i = 0; i < k; ++i) {
                printf("%d
    ", ans[i]);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    python 遍历文件夹 文件
    Docker使用常见问题
    Docker基础技术:DeviceMapper
    更改Docker默认的images存储位置
    NAT方式,宿主机无法ping通虚拟机
    centos7使用问题总结
    VMWare虚拟机提供的桥接、nat和主机模式的区别
    css之'>'
    eclipse安装插件:
    腾讯后台开发面试总结,原创,吐血推荐!!
  • 原文地址:https://www.cnblogs.com/wenruo/p/5813469.html
Copyright © 2011-2022 走看看