1. 程式人生 > >【筆試】今日頭條 - 線段樹查詢

【筆試】今日頭條 - 線段樹查詢

規模 bit pri http tro clu 格式 pair struct

【題目描述】

給定兩個長度為 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\n", B[i]); return 0; }

References

https://www.nowcoder.com/profile/2449601/test/12036803/110438#summary

【筆試】今日頭條 - 線段樹查詢