首页 > 其他分享 >【学习笔记】Segment Tree Beats/吉司机线段树

【学习笔记】Segment Tree Beats/吉司机线段树

时间:2024-11-16 14:30:22浏览次数:1  
标签:rs int res Tree Beats 区间 Segment mx se

链接

区间最值操作

HDU-5306

支持对区间取 \(\min\),维护区间 \(\max\),查询区间和。

很容易想到一个暴力,我们每一次找出这个区间的最大值 \(mx\),如果 \(mx>x\),那么暴力修改这个位置的值,否则已经修改完毕,退出,时间复杂度为 \(O(n^2 \log n)\)。

打一打补丁,对线段树上的每一个区间维护区间最大值 \(mx\),这个区间中最大值出现的次数 \(t\),区间次大值 \(se\),当然还要维护区间和 \(sum\)。

现在考虑打上区间取 \(\min\) 标记

  • 如果 \(mx\le x\),那么对 \(sum\) 就没有修改。
  • 如果 \(se<x<mx\),那么 \(sum=sum-(mx-x)\times t\)。
  • 如果 \(x\le se<mx\),此时无法直接更新节点信息,故向下左右子树递归。我们分别 DFS 这个节点的两个孩子,如果当前 DFS 的过程中遇到了前两种情况,就直接修改打上标记然后退出,否则就继续 DFS。
点击查看代码
#include<bits/stdc++.h>
using namespace std;

#define ls p<<1
#define rs p<<1|1
#define ll long long
inline char gc()
{
    static char buf[1 << 20/*这里很玄学,改成其他数字可能更快*/], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20/*改成和上面一样的数字*/, stdin), p1 == p2) ? EOF : *p1 ++;
}

inline void read(int &n) // 用法 read(n);
{
    bool w = 0;
    char c = gc();
    for(; c < 48 || c > 57; c = gc())
        w = c == 45;
    for(n = 0; c >= 48 && c <= 57; c = gc())
        n = n * 10 + c - 48;
    n = w ? -n : n;
}
const int N=1e6+7;

int T,n,m,a[N],mx[N<<2],se[N<<2],cnt[N<<2],tag[N<<2];
ll sum[N<<2];

inline void pushup(int p){
    sum[p]=sum[ls]+sum[rs];
    if(mx[ls]==mx[rs]){
        mx[p]=mx[ls],se[p]=max(se[ls],se[rs]);
        cnt[p]=cnt[ls]+cnt[rs];
    }
    else if(mx[ls]>mx[rs]){
        mx[p]=mx[ls],se[p]=max(se[ls],mx[rs]);
        cnt[p]=cnt[ls];
    }
    else{
        mx[p]=mx[rs],se[p]=max(se[rs],mx[ls]);
        cnt[p]=cnt[rs];
    }
    return;
}

inline void build(int p,int l,int r){
    tag[p]=-1;
    if(l==r){
        sum[p]=mx[p]=a[l];
        cnt[p]=1,se[p]=-1;
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pushup(p);
    return;
}

inline void pushtag(int p,int tg){
    if(mx[p]<=tg)return;
    sum[p]+=(ll)(tg-mx[p])*cnt[p];
    mx[p]=tag[p]=tg;
    return;
}

inline void pushdown(int p){
    if(tag[p]==-1)return;
    pushtag(ls,tag[p]),pushtag(rs,tag[p]);
    tag[p]=-1;
    return;
}

inline void update(int p,int l,int r,int s,int t,int val){
    if(mx[p]<=val)return;
    if(s<=l&&r<=t&&se[p]<val){
        pushtag(p,val);
        return;
    }
    int mid=(l+r)>>1;
    pushdown(p);
    if(s<=mid)update(ls,l,mid,s,t,val);
    if(t>mid)update(rs,mid+1,r,s,t,val);
    pushup(p);
    return;
}

inline int querymax(int p,int l,int r,int s,int t){
    if(s<=l&&r<=t)return mx[p];
    int mid=(l+r)>>1,res=-1;
    pushdown(p);
    if(s<=mid)res=max(res,querymax(ls,l,mid,s,t));
    if(t>mid)res=max(res,querymax(rs,mid+1,r,s,t));
    return res;
}

inline ll querysum(int p,int l,int r,int s,int t){
    if(s<=l&&r<=t)return sum[p];
    int mid=(l+r)>>1;ll res=0;
    pushdown(p);
    if(s<=mid)res+=querysum(ls,l,mid,s,t);
    if(t>mid)res+=querysum(rs,mid+1,r,s,t);
    return res;
}

inline void solve(){
    read(n); read(m);
    for(int i=1;i<=n;i++)read(a[i]);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int op,l,r,val;
        read(op); read(l); read(r);
        if(!op){
            read(val);
            update(1,1,n,l,r,val);
        }
        else if(op==1)printf("%d\n",querymax(1,1,n,l,r));
        else printf("%lld\n",querysum(1,1,n,l,r));
    }
    return;
}

int main(){
    scanf("%d",&T);
    while(T--)solve();
    return 0;
}

标签:rs,int,res,Tree,Beats,区间,Segment,mx,se
From: https://www.cnblogs.com/LKJZYD20/p/18549071

相关文章

  • LSM-TREE一种高效的索引数据结构
    LSM-tree主要目标是快速地建立索引。B-tree是建立索引的通用技术,但是,在大并发插入数据的情况下,B-tree需要大量的磁盘随机IO,很显然,大量的磁盘随机IO会严重影响索引建立的速度。特别地,对于那些索引数据大的情况(例如,两个列的联合索引),插入速度是对性能影响的重要指标,而读取相对来说......
  • 【小样本分割】VAT:Cost Aggregation Is All You Need for Few-Shot Segmentation
    论文:CostAggregationIsAllYouNeedforFew-ShotSegmentation代码:https://github.com/Seokju-Cho/Volumetric-Aggregation-Transformer目录简介SwinTransformer VAT​编辑VolumeEmbeddingModuleVolumetricTransformerModule Affinity-AwareTransformerDeco......
  • elementPlus中的el-tree
    将接口返回的数据整理成组件支持的数据结构接口返回的数据格式:[{"id":767947,"appName":"生生世世","appBundle":"cds","appStore":2,"link":"www.baidu.com","accountId":"3,68","......
  • 界面控件DevExpress WPF中文教程:TreeList视图及创建分配视图
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。无论是Office办公软件的衍伸产品,还是以数据为中心......
  • cmu15545-数据访问方式:B+树(B+Tree)
    目录基本概念基于磁盘的B+树查询与索引设计选择结点大小(NodeSize)合并阈值(MergeThredshold)变长键(Variable-lengthKeys)结点内部搜索(Intra-NodeSearch)优化手段PointerSwizzlingBε-treesBulkInsertPrefixCompressionDeduplicationSuffixTruncation基本概念基于磁盘的B+树......
  • 力扣 653. 两数之和 IV 二叉树/binary-tree two-sum IV
    数组系列力扣数据结构之数组-00-概览力扣.53最大子数组和maximum-subarray力扣.128最长连续序列longest-consecutive-sequence力扣.1两数之和N种解法two-sum力扣.167两数之和IItwo-sum-ii力扣.170两数之和IIItwo-sum-iii力扣.653两数之和IVtwo-sum-IV力......
  • KDTree求平面最近点对
    更新日志思路对于每一个点都求一边其最短距离,最后统计。详细地,对于每个区间,先与其中点判断并更新距离(注意特判不能是同一点),然后找出在这一节点排序维度上,查询点到中点距离,记作\(D\)。看查询点在中点左侧/右侧,判断去左右区间。(在这一节点排序的维度上。)同侧更新完之后,如果......
  • Matrix-Tree 定理 & BEST 定理
    矩阵树定理感谢这篇文章对我更深层次理解矩阵树定理的帮助。预备知识行列式图的关联矩阵对于一张无向图\(G=(V,E)\),定义其关联矩阵\(M\)为(在此我们给边暂定方向,一条边\(e\)的入点和出点分别为\(\text{in}(e)\)和\(\text{out}(e)\)):\[M_{i,j}=\begin{cases}1&V_i=\t......
  • G. Binary Tree
    “交互的本质是二分”本题的询问次数卡得很严,必须保证每次都能让候选点集合严格缩小一半。因此三选二的时候不能任选,而要选较大的两个点击查看代码#include<bits/stdc++.h>usingnamespacestd;vector<int>a[100005];introot,p,val,s[100005],cnt[100005],va[100005],d......
  • 随机链表 (Randomized Linked List)、随机树 (Randomized Tree)详细解读
    一、随机化数据结构(RandomizedDataStructures)随机化数据结构是通过引入随机性来优化传统数据结构的性能,特别是在最坏情况性能表现较差时。通过随机化,许多原本具有较差时间复杂度的操作可以实现平均O(1)或O(logn)的时间复杂度,减少了最坏情况下的复杂度。常见的随机......