笔试今日头条 - 线段树查询
Posted stackupdown
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔试今日头条 - 线段树查询相关的知识,希望对你有一定的参考价值。
【题目描述】
给定两个长度为 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
以上是关于笔试今日头条 - 线段树查询的主要内容,如果未能解决你的问题,请参考以下文章