【笔试】今日头条 - 线段树查询

【题目描述】

给定两个长度为 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

时间: 2024-11-05 14:40:15

【笔试】今日头条 - 线段树查询的相关文章

XKC&#39;s basketball team【线段树查询】

XKC , the captain of the basketball team , is directing a train of nn team members. He makes all members stand in a row , and numbers them 1 \cdots n1?n from left to right. The ability of the ii-th person is w_iwi? , and if there is a guy whose abili

PAT天梯赛练习题 L3-002. 堆栈(线段树查询第K大值)

L3-002. 堆栈 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有“入栈”(将新元素插入栈顶)和“出栈”(将栈顶元素的值返回并从堆栈中将其删除).现请你实现一种特殊的堆栈,它多了一种操作叫“查中值”,即返回堆栈中所有元素的中值.对于N个元素,若N是偶数,则中值定义为第N/2个最小元:若N是奇数,则中值定义为第(N+1)/2个最小元. 输入格式: 输入第一行给出正整

hdu(3016) Man Down(线段树查询更新+dp)

这道题目可以说是游戏的简化版. 题目的大致意思是: 首先我们只有两种板,一种使能量增加,另一种却使能量减少. 最开始人物站在最高层,然后它一开始有100的生命值,它每次下落只能掉到离他最近的木板上去,当然他只能从左端点或者是右端点往下掉. 但是如果没有板满足如下情况的话,那么他就掉到最底下去了,如果此时他的能量小于等于0的话,那么他就会死亡,那么则输出-1:否则输出他所能获得能量的最大值. 现在的任务是叫你输出最大所能获得最大能量值. 思路: 1)我们要找到当前区间的分别从左右端点下去离他最近的

●【记录】今日上午○线段树

●poj 3225 Help with Intervals ○赘述题目: 给出以下集合操作: 然后有初始的一个空集S,和以下题目给出的操作指令,并输入指令: 要求进行指令操作后,按格式输出集合S: ○题解 (此文标题就告诉了我们要用线段树维护...) 关键难点: 1.此题操作较复杂,如何较简便的进行线段树维护? 看看这位大师的转化: ...把各种操作转化为较为一致的区间修改后,线段树就能"开始表演"了. 2.涉及到开闭区间,又如何搞? xio习的大师的方法: 把输入的左右端点a,b同时

【线段树查询区间最值】poj 3264 Balanced Lineup

1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 const int maxn=50005; 6 struct Seg 7 { 8 int l,r,mi,ma; 9 }tree[maxn*4]; 10 int val[maxn]; 11 12 void build(int l,int r,int i=1) 13 { 14 tree[i].l=l; 15 tree[i].r=r; 16 if (l=

HDOJ 5338 ZZX and Permutations 线段树+树状数组

[题意]: 给一个排列加上表示循环的括号,问如何让1到n的对应的字典序最大. 从1开始贪心每个数字可以往三个地方走,右边第一个,跳转到左边的某一个,和自己构成循环 对于走到右边第一个的情况,只要判断右边的那个有没有被占据就可以了,如果可以和右边的互换,那么需要在线段树中将右边的数置为0 跳转到左边的某一个,一个数如果跳转到左边的某一个则说明左边的那个是括号开头这个数是括号结尾,用一个线段树查询区间里的最大值,由于括号间是不能重叠的,所以需要用树状数组二分一下左边界.如果这个数是要跳转到左边的某个

HDU 4417 Super Mario (树状数组/线段树)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble agai

Gym 100803G 线段树

好长时间前做的题,来补一下题解. 给出括号化的序列,每次改变一个括号方向,求出下标p,是的改变p处的括号方向可以使括号化仍然成立,且p最小. 保证括号化看似和线段树没有联系,我们可以把括号"("表示为1,把括号")"表示为-1,则保证括号化的充要条件就是使数字序列前缀和始终大于等于零 用线段树维护前缀和 查询有两种情况 1. "(" 变成 ")" 这种情况我们只需找到最左边的一个")",就是答案.(可以用一

HDU5266---pog loves szh III (线段树+LCA)

题意:N个点的有向树, Q次询问, 每次询问区间[L, R]内所有点的LCA. 大致做法:线段树每个点保存它的孩子的LCA值, 对于每一次询问只需要 在线段树查询即可. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 3e5+10; 4 struct Edge{ 5 int to, next; 6 }e[MAXN << 1]; 7 int head[MAXN], tot_edge; 8 voi