HDU 4417 线段树离线&&主席树在线-程序员宅基地

技术标签: 数据结构_线段树  数据结构_树链剖分  数据结构_可持久化  ACM/ICPC_ BZOJ  数据结构_主席树  

Problem Description
Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss’s castle as a line (the length is n), on every integer point i there is a brick on height hi. Now the question is how many bricks in [L, R] Mario can hit if the maximal height he can jump is H.

Input
The first line follows an integer T, the number of test data.
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)

Output
For each case, output “Case X: ” (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.

Sample Input
1
10 10
0 5 2 7 5 4 3 8 7 7
2 8 6
3 5 0
1 3 1
1 9 4
0 1 0
3 5 5
5 5 1
4 6 3
1 5 7
5 7 3

Sample Output
Case 1:
4
0
0
3
1
2
0
1
5
1

解法1: 线段树/BIT离线
1,先把所有位置的高度都存下来,然后排序,注意保存下标;2,把所有询问存下来,然后按照询问的高度进行排序,同注意保存下标;3,对于排序后的每次询问的处理:由于每个位置的高度都已经存了下来并且进行了排序,所以可以按照顺序将每个点插入到线段树的对应位置(保存的下标),并更新 线段树,直到要插入的位置的高度大于这次询问的高度H;最后处理区间查询,由于刚才已经把小于等于该次查询高度的位置都已经插入到了线段树中,所以询问的 结果就是查询区间中被更新过的叶子节点的个数,也就是区间求和问题。当然换成BIT也完全一样

//156ms 4.9Mb
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct node{
    int h, pos;
    node(){}
    node(int h, int pos) : h(h), pos(pos){}
    bool operator < (const node &rhs) const{
        return h < rhs.h;
    }
}a[maxn];

struct Q{
    int l, r, h, id;
    Q(){}
    Q(int l, int r, int h, int id) : l(l), r(r), h(h), id(id){}
    bool operator < (const Q &rhs) const{
        return h < rhs.h;
    }
}q[maxn];

int ans[maxn];
namespace segmenttree{
    int sum[maxn*4];
    inline void init(){memset(sum, 0, sizeof(sum));}
    inline void pushup(int o){sum[o] = sum[o*2] + sum[o*2+1];}
    inline void update(int pos, int l, int r, int o){
        if(l == r){
            sum[o]++;
            return ;
        }
        int m = (l + r) / 2;
        if(pos <= m) update(pos, l, m, o*2);
        else update(pos, m + 1, r, o*2+1);
        pushup(o);
    }
    inline int query(int L, int R, int l, int r, int o){
        if(L <= l && r <= R) return sum[o];
        int m = (l + r) / 2;
        if(R <= m) return query(L, R, l, m, o*2);
        else if(L > m) return query(L, R, m + 1, r, o*2+1);
        else return query(L, m, l, m, o*2) + query(m + 1, R, m + 1, r, o*2+1);
    }
}
using namespace segmenttree;
int main(){
    int n, m, T, ks = 0;
    scanf("%d", &T);
    while(T--){
        printf("Case %d:\n", ++ks);
        init();
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i].h), a[i].pos = i;
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].h); q[i].id = i;
        }
        sort(a + 1, a + n + 1);
        sort(q + 1, q + m + 1);
        int i, j;
        for(i = j = 1; i <= m; i++){
            int id = q[i].id, l = q[i].l, r = q[i].r;
            while(a[j].h <= q[i].h && j <= n){
                update(a[j++].pos, 1, n, 1);
            }
            ans[id] = query(l + 1, r + 1, 1, n, 1);
        }
        for(int k = 1; k <= m; k++){
            printf("%d\n", ans[k]);
        }
    }
    return 0;
}

解法2:在线主席树做法,我们知道主席数可以方便的维护区间第k大,那么我们可以在此基础上统计第i小的的数小于k的个数。

//156ms 11.1MB
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int maxm = 30*maxn;
int n, m, q, tot, a[maxn], b[maxn];
int getid(int x){
   return lower_bound(b + 1, b + m + 1, x) - b; }//下标从1开始
namespace chairmantree{
    int T[maxm], lson[maxm], rson[maxm], c[maxm];
    int build(int l, int r){
        int root = tot++;
        c[root] = 0;
        if(l != r){
            int mid = (l + r) / 2;
            lson[root] = build(l, mid);
            rson[root] = build(mid + 1, r);
        }
        return root;
    }
    int update(int root, int pos, int val){
        int newroot = tot++, tmp = newroot;
        c[newroot] = c[root] + val;
        int l = 1, r = m;
        while(l < r){
            int mid = (l + r) / 2;
            if(pos <= mid){
                lson[newroot] = tot++, rson[newroot] = rson[root];
                newroot = lson[newroot], root = lson[root], r = mid;
            }
            else{
                rson[newroot] = tot++, lson[newroot] = lson[root];
                newroot = rson[newroot], root = rson[root], l = mid + 1;
            }
            c[newroot] = c[root] + val;
        }
        return tmp;
    }
    int query(int L, int R, int k){
        int res = 0;
        int l = 1, r = m;
        while(l < r){
            int mid = (l + r) / 2;
            if(k <= mid){
                r = mid;
                L = lson[L];
                R = lson[R];
            }
            else{
                l = mid + 1;
                res += c[lson[R]] - c[lson[L]];
                L = rson[L];
                R = rson[R];
            }
        }
        return res + (k < l ? 0 : c[R] - c[L]);
    }
}
using namespace chairmantree;

int main(){
    int TT, ks = 0;
    scanf("%d", &TT);
    while(TT--){
        printf("Case %d:\n", ++ks);
        scanf("%d%d", &n, &q);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++) b[i] = a[i];
        sort(b + 1, b + n + 1);
        m = unique(b + 1, b + n + 1) - b - 1;
        T[0] = build(1, m);
        for(int i = 1; i <= n; i++) T[i] = update(T[i-1], getid(a[i]), 1);
        while(q--){
            int l, r, h;
            scanf("%d%d%d", &l, &r, &h);
            h = upper_bound(b+1, b+m+1, h) - b - 1;//有重复元素,所以要找upper_bound
            printf("%d\n", query(T[l], T[r+1], h));
        }
    }
    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/just_sort/article/details/58154832

智能推荐

基于python的信用卡评分模型_python 信用 评分卡模型-程序员宅基地

文章浏览阅读4.4w次,点赞45次,收藏418次。基于python的信用卡评分模型1. 项目背景介绍1.1 信用风险和评分卡模型的基本概念 信用风险指的是交易对手未能履行约定合同中的义务造成经济损失的风险,即受信人不能履行还本付息的责任而使授信人的预期收益与实际收益发生偏离的可能性,它是金融风险的主要类型。 借贷场景中的评分卡是一种以分数的形式来衡量风险几率的一种手段,也是对未来一段时间内违约、逾期、失联概率的预测。一般来说..._python 信用 评分卡模型

linux 下 tcpdump 详解 前篇(libpcap库源码分析)_libcap 源码-程序员宅基地

文章浏览阅读1.7k次,点赞3次,收藏22次。一 概述用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具。 至于tcpdump参数如何使用,这不是本章讨论的重点。liunx系统抓包工具,毫无疑问就是tcpdump。而windows的抓包工具,wireshark也是一款主流的抓包工具。wireshark 使用了winpcap库。tcpdump..._libcap 源码

http://mirrors.aliyun.com/epel/6/x86_64/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 --程序员宅基地

文章浏览阅读6.5k次,点赞14次,收藏11次。http://mirrors.aliyun.com/epel/6/x86_64/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 - “The requested URL returned error: 404 Not Found”Trying other mirror.Error: Cannot retrieve repository metadata (repomd.xml) for repository: epel. Please verify its_/epel/6/x86_64/repodata/repomd.xml: [errno 14] pycurl error 22 - "the reques

Audio System 九 之 AudioTrack_audiotrackserverproxy-程序员宅基地

文章浏览阅读1k次。Audio System 九 之 AudioTrack十四、AudioTrack & AudioFlinger 相关类14.1 AudioTrack & AudioFlinger 的类图14.1.1 AudioFlinger::PlaybackThread 回放线程基类14.1.2 AudioFlinger::PlaybackThread::Track 音频流管理类14.1...._audiotrackserverproxy

Redis 通用命令(keys,help,mset,exists,expire,ttl,tab补全)_redis如何添加help命令-程序员宅基地

文章浏览阅读874次。redis 通用命令 _redis如何添加help命令

google chromeDriver 地址

chrome driver 下载地址。#chrome brower下载地址。#安装openssl 1.1.1K。#安装chrome driver。#安装browser。

随便推点

实现RTSP摄像机进行网页直播和微信直播的技术方案:EasyNVR版本免费更新方法_easynvr免费版-程序员宅基地

文章浏览阅读2.7k次。问题背景前文我们提过为保障服务器正常稳定运作,EasyNVR有专业的运维(售前支撑、商务咨询、售后维护)团队,随时对客户各种突发情况快速响应处理,保证互联网直播的顺利进行。这部分工作就包括技术问题咨询、需求分析、方案制定、版本更新、功能提升等,随着用户基数的增加,运维过程中或多或少存在一些回复延迟,主要包括以下几个方面:EasyNVR的用户越来越多,技术人员一一对应解答效率不高;随着Eas..._easynvr免费版

P1541 [NOIP2010 提高组] 乌龟棋 题解_乌龟棋2010-程序员宅基地

文章浏览阅读401次,点赞3次,收藏4次。更好的阅读体验蒟蒻的第一篇题解P1541 [NOIP2010 提高组] 乌龟棋简单的背包 首先确定状态,dp[a][b][c][d]用来存储使用a张爬行卡片1,b张爬行卡片2,c张爬行卡片3,d张爬行卡片4时的最大得分。 我们需要开一个桶的数组t存4种牌的个数,以便于暴力。 dp数组初始化。很显然,四种卡片都用0张时,在起点,分数为score[1] 即: dp[0][0][0][0]=score[1]; 状态转移。DP 4种卡片的个数,状态转移方程为_乌龟棋2010

计算机网络 | 划分子网_计算机网络子网划分-程序员宅基地

文章浏览阅读5.5k次,点赞11次,收藏69次。划分子网概念先知了解 什么是子网?了解 为什么要划分子网?划分子网的好处/优点是什么?介绍 子网掩码总结 子网掩码记住 IP 地址的自然分类问题求解一个网络,主机号有x位,则这个网络可以分配给主机的IP地址有多少个?子网划分实例问题1题目分析题目解题方法参考内容概念先知了解 什么是子网?子网或子网络是网络内部的网络。子网使网络更高效。通过子网划分,网络流量传播距离更短,无需通过不必要的路由器即可到达目的地。了解 为什么要划分子网?划分子网的好处/优点是什么?1.减少广播带来的负面影响2.节_计算机网络子网划分

Java利用JNA调用C#的dll-程序员宅基地

文章浏览阅读7.3k次,点赞2次,收藏23次。https://www.cnblogs.com/wyongbo/p/jnaTest.html本文参考以上链接,结合自己实际遇到的问题,做过一些修改(红色字体标注),主要是为了给自己做个笔记。一、需求阐述:  如果我们的项目利用c#开发,到了开发后期需要和java组进行合作,其中有一部分业务逻辑利用c#已经code completed,那么我们可能会考虑用java来调用现成的c#dll实...

linux查看系统编码和修改系统编码的方法_linux 机器编码设置-程序员宅基地

文章浏览阅读1.4w次。查看支持的字符编码使用locale命令,如:. 代码如下:# localeLANG=en_US.UTF-8LC_CTYPE="en_US.UTF-8"LC_NUMERIC="en_US.UTF-8"LC_TIME="en_US.UTF-8"LC_COLLATE="en_US.UTF-8"LC_MONETARY="en_US.UTF-8"LC_MESSAG_linux 机器编码设置

企业微信小程序_小程序开发工具及真机调试_host配置及代理_微信开发者工具 本地代理-程序员宅基地

文章浏览阅读7.6k次。文章目录一、开发前准备1. 开发文档2. 工具安装3. 安装插件4. 调整编译模式5. 选择企业6. PC 调试前端7. PC 调试后端二、甄姬调试前端2.1. 预览小程序2.2. 手机企微扫码2.3. 手机企微调试2.4. 多场景调试2.5. 手机企微调试前后端一、开发前准备1. 开发文档小程序开发文档:https://developer.work.weixin.qq.com/document/path/91502点击企业微信小程序开发进入详情页面2. 工具安装微信开发者工具3. ._微信开发者工具 本地代理