值域线段树 (玲珑OJ 1117)

经典算法:Fenwick Tree 经典算法:Fenwick Tree (Binary Indexed Tree) 阅读详情

点击打开题目链接

题目意思很简单:

1、插入x
2、把小于x的数变成x
3、把大于x的数变成x
4、求集合中第x小数
5、求集合中小于x的数个数


思路: 线段树,节点是值的分数,你可以离散,也可以不离散,直接标记;我的写法是:   看代码注释>>>


据说数组改为指针会快点;代码比较挫.存一个;

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;

typedef long long int LL;
const LL INF=1000000000;
const int maxn=6e6+100;


struct ACM
{
    struct segment
    {
        int val,lson,rson;
        bool mark;
    } seg[maxn];
    int sz;
    /***
        开辟新的节点并初始化
    */
    int newnode()
    {
        sz++;
        if(sz>=maxn)
        {
            int lzq=5,zhangpan=0;
            lzq=lzq/zhangpan;

        }
        seg[sz].lson=seg[sz].rson=-1;
        seg[sz].val=0,seg[sz].mark=false;
        return sz;
    }
    /***
        初始化根节点
    */
    void init(int& root)
    {
        sz=-1;
        root=newnode();
    }
    /***
        标记下放操作,如果没有节点开辟新的节点;
    */
    void pushdown(int i) 
    {
        int l=seg[i].lson,r=seg[i].rson;
        if(l==-1) seg[i].lson=newnode();
        if(r==-1) seg[i].rson=newnode();
        if(seg[i].mark)
        {
            seg[i].mark=false;
            seg[l].mark=seg[r].mark=true;
            seg[l].val=seg[r].val=0;
        }
    }
    void pushup(int i)
    {
        int l=seg[i].lson,r=seg[i].rson;
        seg[i].val=seg[l].val+seg[r].val;
    }
    /***
        插入函数 ; 在 pos 位置上面加上 val;
    */
    void ins(int i,int l,int r,int pos,int val)
    {
        if(l==r)
        {
            seg[i].val+=val;
            return ;
        }
        pushdown(i);
        int mid=(l+r)>>1;
        if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
        else ins(seg[i].rson,mid+1,r,pos,val);
        pushup(i);
    }
    /***
        将 L,R 这段区间上的值,更新为 0;
    */
    void del(int i,int l,int r,int L,int R)
    {
        if(l==L&&r==R)
        {
            seg[i].val=0;
            seg[i].mark=true;
            return ;
        }
        pushdown(i);
        int mid=(l+r)>>1;
        if(R<=mid) del(seg[i].lson,l,mid,L,R);
        else if(L>mid) del(seg[i].rson,mid+1,r,L,R);
        else del(seg[i].lson,l,mid,L,mid),del(seg[i].rson,mid+1,r,mid+1,R);
        pushup(i);
    }
    int find(int i,int l,int r,int x) //第x小的数字;
    {
        if(l==r) return l;
        pushdown(i);
        int lval=0;
        int mid=(l+r)>>1;
        if(seg[i].lson!=-1) lval=seg[seg[i].lson].val;
        if(x<=lval) return find(seg[i].lson,l,mid,x);
        else return find(seg[i].rson,mid+1,r,x-lval);
    }
    int query(int i,int l,int r,int L,int R) //区间 数的个数;
    {
        if(l==L&&r==R) return seg[i].val;
        pushdown(i);
        int mid=(l+r)>>1;
        if(R<=mid) return query(seg[i].lson,l,mid,L,R);
        else if(L>mid) return query(seg[i].rson,mid+1,r,L,R);
        else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+1,r,mid+1,R);
    }
} AC;



int main()
{
    int m;
    scanf("%d",&m);
    int op,x,root,temp;
    AC.init(root);
    while(m--)
    {
        scanf("%d%d",&op,&x);
        switch(op)
        {
        case 1:
            AC.ins(root,0,INF,x,1);
            break;
        case 2:
            temp=AC.query(root,0,INF,0,x);
            AC.del(root,0,INF,0,x);
            AC.ins(root,0,INF,x,temp);
            break;
        case 3:
            temp=AC.query(root,0,INF,x,INF);
            AC.del(root,0,INF,x,INF);
            AC.ins(root,0,INF,x,temp);
            break;
        case 4:
            printf("%d\n",AC.find(root,0,INF,x));
            break;
        case 5:
            printf("%d\n",AC.query(root,0,INF,0,x-1));
            break;
        }
    }
    return 0;
}

代码二:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;

const int INF=1000000000;
const int maxn=6e6+100;
struct ACM
{
    /***
        对于 2,3 操作,先查询个数,再插入这个数字:
        意思就是更新到底部,加上查询出来的个数;
        并加上清零的标记;
        
    */
    struct Node
    {
        int val,lson,rson;
        bool mark;
    } seg[maxn];
    int sz;
    int newnode()
    {
        sz++;
        seg[sz].val=0;
        seg[sz].lson=-1;
        seg[sz].rson=-1;
        seg[sz].mark=false;
        return sz;
    }
    void init(int& root)
    {
        sz=-1;
        root=newnode();
    }
    void pushdown(int i)
    {
        int l=seg[i].lson,r=seg[i].rson;
        if(l==-1) seg[i].lson=newnode();
        if(r==-1) seg[i].rson=newnode();
        if(seg[i].mark)
        {
            seg[i].mark=false;
            seg[l].mark=seg[r].mark=true;
            seg[l].val=seg[r].val=0;
        }
    }
    void pushup(int i)
    {
        int l=seg[i].lson,r=seg[i].rson;
        seg[i].val=seg[l].val+seg[r].val;
    }
    int query(int i,int l,int r,int L,int R) //区间 数的个数;
    {
        if(l==L&&r==R) return seg[i].val;
        pushdown(i);
        int mid=(l+r)>>1;
        if(R<=mid) return query(seg[i].lson,l,mid,L,R);
        else if(L>mid) return query(seg[i].rson,mid+1,r,L,R);
        else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+1,r,mid+1,R);
    }
    void ins(int i,int l,int r,int pos,int val)
    {
        if(l==r)
        {
            seg[i].val+=val;
            return ;
        }
        pushdown(i);
        int mid=(l+r)>>1;
        if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
        else ins(seg[i].rson,mid+1,r,pos,val);
        pushup(i);
    }
    void operator2(int i,int l,int r,int x,int val)
    {
        if(l==r)
        {
            seg[i].val=val;
            return ;
        }
        int mid=(l+r)>>1;
        pushdown(i);
        if(x<=mid) operator2(seg[i].lson ,l,mid,x,val);
        else
        {
            seg[seg[i].lson].mark=true;
            seg[seg[i].lson].val=0;//如果,存在加到某一边,不存在也需要开新的节点!!
            operator2(seg[i].rson,mid+1,r,x,val);
        }
        pushup(i);
    }
    void operator3(int i,int l,int r,int x,int val)
    {
        if(l==r)
        {
            seg[i].val=val;
            return ;
        }
        pushdown(i);
        int mid=(l+r)>>1;
        if(x<=mid)
        {
            seg[seg[i].rson].mark=true;
            seg[seg[i].rson].val=0;
            operator3(seg[i].lson,l,mid,x,val);
        }
        else operator3(seg[i].rson,mid+1,r,x,val);
        pushup(i);
    }
    int operator4(int i,int l,int r,int x)
    {
        if(l==r) return l;
        int mid=(l+r)>>1;
        pushdown(i);
        int val=seg[seg[i].lson].val;
        if(x<=val) return operator4(seg[i].lson,l,mid,x);
        else return operator4(seg[i].rson,mid+1,r,x-val);
    }
} AC;


int main()
{

    int m;
    while(scanf("%d",&m)!=EOF)
    {
        int op,x,root,temp;
        AC.init(root);
        while(m--)
        {
            scanf("%d%d",&op,&x);
            switch(op)
            {
            case 1:
                AC.ins(root,0,INF,x,1);
                break;
            case 2:
                temp=AC.query(root,0,INF,0,x);
                AC.operator2(root,0,INF,x,temp);
                break;
            case 3:
                temp=AC.query(root,0,INF,x,INF);
                AC.operator3(root,0,INF,x,temp);
                break;
            case 4:
                printf("%d\n",AC.operator4(root,0,INF,x));
                break;
            case 5:
                printf("%d\n",AC.query(root,0,INF,0,x-1));
                break;
            }
        }
    }
    return 0;
}


【算法】值域线段树 简单介绍值域线段树 阅读详情

相关推荐

最长上升子序列 + 优化(线段树、树状数组)

最长上升子序列 + 优化(线段树、树状数组)

lins 1784

线段树——将区间中的所有数修改为某个值

题目:hdu1698 Just a Hook 题目大意: 每次操作给出三个数x,y,z:表示将区间[x,y]中的所有值变为z 查询某个区间的所有数的和(注:本题没有这一要求,但此代码可以实现这个操作) 输出m次操作后,所有数的和 代码实现: #include &lt;bits/stdc++.h&gt; using namespace std; typedef long long in...

AcTarjan的博客 3593

高级数据结构之Fenwick Tree(Binary Indexed Tree)

Fenwick Tree也叫做树状数组,或者二叉索引树(BIT,Binary Indexed Tree),由新西兰奥克兰大学的Peter Fenwick博士于1994年提出。Fenwick Tree用数组来表示一棵树(这样空间上更节约),所以它的结点中没有指向左右孩子的指针这样的设计。它可以用于对区间和(range sum)进行快速查询,其元素修改和区间查询的复杂度都是O(log n)

白马负金羁 1078

P1253 扶苏的问题

题目描述。

weixin_61067952的博客 533

高级数据结构 - 线段树、权值线段树(Java & JS & Python)

线段树、权值线段树

优快云 946

ArduSub深度调参指南:如何让水下机器人像鱼一样稳定游动

本文深入探讨了ArduSub水下机器人的深度调参策略,旨在解决ROV在水下晃动、响应迟钝等问题。文章系统解析了级联PID控制逻辑,并针对静水与水流环境,提供了具体的深度保持与姿态控制调参方法、实战日志分析技巧以及异常振荡处理方案,帮助用户实现水下机器人稳定、流畅的游动性能。

CAT789的专栏 372

吉司机线段树--区间最值操作

区间最值操作 给定一个长度为 N序列,编号从1 到 N。要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于x 的数变成x 4.求区间[L,R] 的和 5.求区间[L,R] 的最大值 6.求区间[L,R] 的最小值 最假女选手 #include<bits/stdc++.h> #include <unordered_map> using namespace std; template<c

weach的博客 671

麦当劳app之sign逆向分析

摘要:本文分析了麦当劳APP请求参数sign的逆向过程。通过抓包发现32位sign参数疑似MD5加密,使用frida-trace工具跟踪CC_MD5函数验证其为标准MD5算法。加密参数包含时间戳、token、版本号等固定和动态字段,拼接后经MD5加密生成sign。文章提供了JS和Python两种实现方案,包含完整的请求头参数和加密逻辑,最终成功获取API响应数据。该研究仅用于逆向技术学习,展示了移动应用常见加密参数的逆向分析方法。

佛系更新... 2437

玲珑杯Round #14 B题 RE:从零开始的异世界生活(离线+线段树)

题意:www.ifrog.cc/acm/problem/1117分析:题解中给出了三种方法,但都需要一些我不会的数据结构,我给出我的方法——离线+线段树。你要问我怎么想到用线段树的?那我很抱歉地告诉你,我也不知道,就是赛后灵光一闪。对!没错!是赛后!为什么不是比赛的时候啊!!!查询先不看,先看修改。操作一是插入一个数,没什么特别的;操作二是把所有小于x的数变成x,那么我这时就想到了要建立一个类似标签

shengtao96的专栏 726

轻量级NAS的隐秘战场:比特米盒CumeBox2与CasaOS的生态融合实践

本文探讨了比特米盒CumeBox2轻量级NAS设备与CasaOS操作系统的生态融合实践。通过硬件选型、系统部署、性能优化和应用场景分析,展示了如何将CumeBox2与CasaOS深度整合,打造经济实用的家庭数据管理中心,特别适合入门级用户和小型办公环境。

rl6adventurer的博客 895

深入解析安卓/Linux固件:从DTB到DTS的反编译实战

本文详细介绍了如何从安卓/Linux设备固件中提取并反编译DTB文件,将其转换为可读的DTS源码。通过实战步骤,包括拆解boot.img、处理resource.img以及使用dtc工具,帮助开发者深入理解设备硬件配置,为固件定制、驱动调试和系统移植提供关键支持。

weixin_29274337的博客 339

树:Fenwick Tree | 二叉索引树

概述二进制索引树是一种数据结构,用于有效地计算数字序列(数组)的前缀和。它也被称为芬威克树,因为“彼得芬威克”通过他的论文将其介绍给世界“于1994年首次发布。Fenwick Tree简介当回答关于数组的多个前缀和(从索引 0 到索引 x 的数组元素之和,即 a[0]+a[1]+...+a[x])查询时,我们脑海中首先浮现的想法是使用一个前缀和数组。在这里,如果我们想计算a[0]+a[1]+...+a[4],我们不需要计算它,而是我们可以简单地。

新华编程特战队 2323

rknn-toolkit推理yolov5-face.rknn模型--python代码

import os import urllib import traceback import time import sys import numpy as np import cv2 from rknn.api import RKNN ONNX_MODEL = 'yolov5s.onnx' RKNN_MODEL = 'yolov5s.rknn' IMG_PATH = './bus.jpg' DATASET = './dataset.txt' QUANTIZE_ON = True BOX_THR.

C/C++、嵌入式开发、深度学习算法、模型部署与推理优化 3079

值域线段树

题目链接 题目可转化为值域线段树的写法,题目上说让求所有区间和的值在L到R之间的有多少个,每一个区间值可以由数组的前缀和快速求出来,设sum[i]为i之前的和,i小于j即求sum[j]-sum[i]在L到R之间的有多少个,可以转化为 sum[j]-R<=sum[i]<=sum[j]-L,用sum[i]建一颗值域线段树每次询问在sum[j]-R到sum[j]-L之间的值有多少个累加起来就是结果。/

ACMer_ZP的博客 1272

【BlueDroid】蓝牙音乐协议分析之A2DP和AVRCP连接流程(超详细)

AVCTP协议描述了蓝牙设备间Audio/Video的控制信号交换的格式和机制,他是一个总体的协议,具体的控制信息由其指定的协议(AVRCP)实现,AVCTP协议本身只指定控制Command和Response的总体的格式;这个过程中对应了Event中的btavrcp_play_status_changed_callback和btavrcp_play_position_changed_callback;上述为AVCTP-Control建立L2CAP连接的Command,对应H4的Sent (0x00);

风云说通信 7314

2024 全国大学生新质生产力大赛 B:金融违规交易的大数据分析 问题四思路代码

问题四:请分析附件中所有的指标数据,选取合适的指标,建立“金融违规 洗钱交易的预测模型”,并选取合适的训练集和测试集,计算预测模型的准确率。 为了提前识别并预测金融违规洗钱的交易事件,请基于你们团队数据分析的结果, 分别给公安部门和银行机构提出你们的建议。

YOLO 375

二叉树算法之 Fenwick 树(Binary Indexed Tree, BIT)详细解读

Fenwick 树,也称为 树状数组 或 二进制索引树(Binary Indexed Tree, BIT),是一种用于处理动态数组前缀和查询和修改的数据结构。它提供了一种高效的方法来在动态数据中求解区间和问题,并支持单点更新和区间查询操作。

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 2140

ROS2入门到精通—— 1-1 Linux和ROS2基础

本文介绍了Linux的一般指令以及ROS2的常见理论和操作

BigDavid123的博客 3804

【模板】权值线段树(值域线段树)

原文 顾名思义,维护权值的线段树。在一定情况下可以代替平衡树使用。 原理是用线段树维护桶,节点维护子树中数的个数。所以空间开销与数据的值域相关。 那要是值域过大怎么办:离散化和动态开点,离散化可以将数据值域缩小到数据数量,将空间复杂度变为 O(n)O(n)O(n),缺点是需要离线。而需要在线则需支持动态开点,即用多少开多少。 动态开点线段树 权值线段树:支持平衡树操作(翻转除外),并附带离散化 P3369普通平衡树 #include<bits/stdc++.h> using namespace

cbdsopa的博客 770

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

6.10 Fenwick树

本文详细介绍了Fenwick树的原理。

你的指尖有改变世界的力量 1633

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

初涉值域线段树

其实就是线段树啦 什么是值域线段树 我们(初学者)都知道线段树是拿来维护数列区间的信息的。但是如果我们想要查询的重点在于数值而不是区间信息呢?这时候就要对于值域区间维护线段树了。 例题 bzoj4627: [BeiJing2016]回转寿司 题目大意 给定$n$个数和$L,R$,问其中区间和满足$L<=sum[r]-sum[l-1]<=R$的区间有多少 N≤100...

weixin_30663471的博客 199

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

树状数组(Fenwick Tree)详解:从原理到实战

树状数组(Fenwick Tree)是一种用于高效处理前缀和查询与单点更新的数据结构。它能在 O(log n) 时间内完成这两种操作,空间复杂度为 O(n),比朴素的前缀和数组(更新 O(n),查询 O(1))和线段树(功能更强但代码更复杂)在特定场景下更加简洁高效。频繁修改数组中的某个元素频繁查询数组某个前缀区间的和树状数组是一种优雅高效的数据结构,特别适合处理前缀和相关的动态统计问题。代码简洁:核心操作仅需几行代码效率高:O(log n) 的时间复杂度满足大多数竞赛和工程需求扩展性强。

QY8765的博客 391

valkey:深入理解 Fenwick Tree(BIT)

valkey 中bit的应用

happytree001的博客 815
上一篇: 线段树-矩形面积求并
下一篇: .vimrc
Code--Dream
博客等级 码龄11年 53粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值