zoukankan      html  css  js  c++  java
  • 【笔试】今日头条

    【题目描述】

    给定两个长度为 n 的整数数列 A 和 B。再给定 q 组查询,每次查询给出两个整数 x 和 y,求满足 Ai >= x 且 Bi >= y 这样的 i 的数量。

    输入格式

    第一行给定两个整数 n 和 q。

    第二行给定数列 A,包含 n 个整数。

    第三行给定数列 B,包含 n 个整数。

    接下来 q 行,每行两个整数 x 和 y,意义如上所述。

    输出格式

    对于每组查询,输出所求的下标数量。

    输入样例

    3 2

    3 2 4

    6 5 8

    1 1

    4 8

    输出样例

    3

    1

    数据规模

    对于 30% 的数据,1 <= n, q <= 100。

    对于 100% 的数据,1 <= n, q, Ai, Bi <= 10^5。

    题解


    想用暴力解法是可以通过一些的, 但是复杂度 O(N^2), 对10^5就不行了。

    树状数组的做法复杂度平均在O(NlogN)。

    #include <bits/stdc++.h>
    using namespace std;//先以A对pair (A, B)排序, 树状数组维护i以后的比y大的个数
    const int maxn = 100000 + 10;
    struct node {
        int x, y, pos;
        bool operator < (const node &a) const {
            if (x == a.x)
                return y<a.y;
            return x<a.x;
        }
    }p[maxn], q[maxn];
    int A[maxn];
    int B[maxn];
    int lowbit(int i) {
        return i & (-i);
    }
    void add(int a, int i) {
        while (i <= maxn-1) {
            A[i] += a;
            i += lowbit(i);
        }
    }
    int sum(int i) {
        int res = 0;
        while (i >= 1) {
            res += A[i];
            i -= lowbit(i);
        }
        return res;
    }
    int main() {
        int n, m;
        cin >> n >> m;
        for(int i = 0; i < n; i++) scanf("%d", &p[i].x);
        for(int i = 0; i < n; i++) scanf("%d", &p[i].y);
        sort(p, p+n);
        for(int i = 0; i < m; i++) {
            scanf("%d%d", &q[i].x, &q[i].y);
            q[i].pos = i;
        }
        for(int i = 0; i < n; i++)
            add(1, p[i].y);
        sort(q, q+m);
        int k = 0;
        for (int i = 0; i < n; i++) {
            if (p[i].x < q[k].x)
                add(-1, p[i].y);
            else {
                while (1) {
                    B[q[k].pos] = sum(maxn - 1) - sum(q[k].y - 1);
                    k++;
                    if (k >= m)
                        break; 
                    if (p[i].x < q[k].x) {
                        add(-1, p[i].y);
                        break;
                    }
                }
            }
            if (k >= m)
                break;
        }
        for (int i = 0; i < m; i++)
            printf("%d
    ", B[i]);
        return 0;
    }

    References

      线段树模板 (刘汝佳)  http://www.cnblogs.com/xianbin7/p/4489655.html

      线段树原理PPT(刘汝佳) https://wenku.baidu.com/view/fe91a24433687e21af45a9e4.html

  • 相关阅读:
    hdu 2044 一只小蜜蜂
    HDU 2041 超级楼梯
    卡特兰数
    hdu 1267 下沙的沙子有几粒?(二维递推题)
    大数加法、乘法
    学习时仪式感太强是不是不太好
    php记日志
    cygwin安装apt-cyg
    存储过程死循环之后的清理
    linux的计划任务crontab
  • 原文地址:https://www.cnblogs.com/wangzming/p/7768761.html
Copyright © 2011-2022 走看看