首页 > 其他分享 >线段树模板

线段树模板

时间:2023-10-04 21:00:25浏览次数:33  
标签:qr const int 线段 mid long STree 模板

应该是做的最认真的模板了。。。

namespace xds{
    template<class T,const int MYMAXSIZE,T (*fun)(T a,T b)>
    class STree{
    private:
        T t[MYMAXSIZE<<2],tag[MYMAXSIZE<<2],a[MYMAXSIZE];
        int num;
        inline const int ls(const int x){return x<<1;}
        inline const int rs(const int x){return x<<1|1;}
        void push_up(const int x){t[x]=fun(t[ls(x)],t[rs(x)]);}
        inline void f(const T&x,const int&l,const int&r,const T&k){
		    tag[x]=fun(tag[x],k);
		    t[x]=fun(t[x],k*(r-l+1));
		}
		inline void push_down(const T&x,const int&l,const int&r){
		    const T mid=(l+r)>>1;
		    f(ls(x),l,mid,tag[x]);
		    f(rs(x),mid+1,r,tag[x]);
		    tag[x]=0;
		}
		inline void update(const int&l,const int&r,const T&k,const int&ql,const int&qr,const int&x){
		    if(l<=ql&&r>=qr){//完全覆盖 
		        t[x]=fun(t[x],k*(qr-ql+1));
		        tag[x]=fun(tag[x],k);
		        return;
		    }
		    push_down(x,ql,qr);
		    const T mid=(ql+qr)>>1;
		    if(l<=mid)update(l,r,k,ql,mid,ls(x));
		    if(r>mid)update(l,r,k,mid+1,qr,rs(x));
		    push_up(x);
		}
		inline T query(const int l,const int r,const int ql,const int qr,const int x){
		    T res=0;
			int mid=(ql+qr)>>1;
		    if(l<=ql&&qr<=r)return t[x];
		    push_down(x,ql,qr);
		    if(l<=mid)res+=query(l,r,ql,mid,ls(x));
		    if(r>mid)res+=query(l,r,mid+1,qr,rs(x));
		    return res;
		}
    public:
        STree():num(MYMAXSIZE-1){}
		STree(const int n):num(n){}
        inline T &operator[](const int i){return a[i];}
        void build(const int x=1,const int l=1,int r=-1){
        	if(r<0)r=num;
            tag[x]=0;
            if(l==r){t[x]=a[l];return;}
            const int mid=(l+r)>>1;
            build(ls(x),l,mid);
            build(rs(x),mid+1,r);
            push_up(x);
        }
		inline void update(const int&l,const int&r,const T&k){
		    push_down(1,1,num);
		    const T mid=(1+num)>>1;
		    if(l<=mid)update(l,r,k,1,mid,ls(1));
		    if(r>mid)update(l,r,k,mid+1,num,rs(1));
		    push_up(1);
		}
		inline T query(const int l,const int r){
		    T res=0;
			int mid=(1+num)>>1;
		    if(l<=1&&num<=r)return t[1];
		    push_down(1,1,num);
		    if(l<=mid)res+=query(l,r,1,mid,ls(1));
		    if(r>mid)res+=query(l,r,mid+1,num,rs(1));
		    return res;
		}
		inline int&getnum(){return num;} 
		inline T&scan(int x){return a[x];}
    };
}
  • 用法:xds::STree<线段树所存储的数据类型,数据范围(线段树最大存储的数据数量),操作方法(函数)>
  • 注意:
  1. 创建线段树时能且只能使用以下两种方法 (如果发现更多使用方法或修改方法求评论或私信,不胜感激)
xds::STree<int,100009,add> *tree=new xds::STree<线段树所存储的数据类型,数据范围(线段树最大存储的数据数量),操作方法(函数)>(输入的数据个数,即数列数字的个数);
xds::STree<线段树所存储的数据类型,数据范围(线段树最大存储的数据数量),操作方法(函数)> tree();
#include<bits/stdc++.h>
using namespace std;
//【此处补充上述模板,由于代码过长,此处省略】
long long add(long long a,long long b){
    return a+b;
}
inline long long read(){
    register long long x = 0, t = 1;
    register char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*t;
}
int main(){
    long long n=read(),m=read(),op,x,y,k;
    xds::STree<long long,100009,add> *tree=new xds::STree<long long,100009,add>(n);
//    xds::STree<int,100009,add> tree();tree.num=n;
	for(int i=1;i<=n;i++)tree->scan(i)=read();
//	for(int i=1;i<=n;i++)tree[i]=read();
	tree->build();
	while(m--){
		op=read();
		switch(op){
			case 1:
				x=read(),y=read(),k=read();
				tree->update(x,y,k);
				break;
			case 2:
				x=read(),y=read();
				printf("%lld\n",tree->query(x,y));
		}
	}
}

注释处暂时由bug,抽空整。


鸣谢:

  1. 皎月半洒花管理大大的题解

标签:qr,const,int,线段,mid,long,STree,模板
From: https://www.cnblogs.com/WangBF/p/17742733.html

相关文章

  • 【数据结构】- 线段树
    线段树简介线段树是可以维护区间信息的数据结构。线段树将每个长度不为\(1\)的区间划分成左右两个区间递归求解,故把整个线段划分为一个树形结构,通过合并左右两区间信息来求得该区间的信息。根据建树方式可分为普通线段树和动态开点线段树。根据区间信息可分为普通线段树......
  • 系统架构设计师论文模板
    摘要XXXX年XX月,我作为XXXX(工作职责),负责XXXXX公司XXXXXXXX的建设项目的开发工作,该项目为期XXXX(项目周期),项目经费为XXXX(项目经费),通过该项目,实现XXXXXXX(项目的实现目标)。该项目XXXXXXXX(实施情况)。该项目于XXXX年XX月开始,于XXXX年XX月完成系统上线,XXXX年XX月通过最终验收,得到......
  • note 线段树
    适用场景:不断区间修改、区间询问。假设我们要区间求和,\(tree\)的含义:区间的和,其两个子节点为这个区间分为两半的和。我们把一个数组\(a\)看作一颗树\(tree\),例:112333对应的\(tree\)(\(()\)里是编号,\([]\)里是对应的区间):(1)13[1,6]/......
  • 线段树专题复习
    今天的主题是线段树专题复习!(什么?是昨天的?不听不听,只要我不说都不知道我鸽了一天!)好了,言归正传,我们来看一下今天的知识点们吧。Part1线段树自己不想讲了,想看的移步其他博客想看踢我,今天没时间了Part2一些优化ZKW线段树俗称重口味线段树,是一种不用递归实现的线段树,常数和......
  • 模板渲染的使用
    现在一般都是前后端分离开发了,模板相对较少使用。和django一样,flask也是支持模板渲染的。flask中默认使用的是jinjia2模板渲染语言。#template_folder:指定模板文件查找的目录(默认就是templates)app=Flask(__name__,template_folder="templates")使用模板渲染返回,前面r......
  • 算法:线段树
    算法:线段树哦吼!终于来学线段树啦~~拖了好久都没有敢学,主要是基础知识点不熟,代码能力太弱。但是现在已经是时候了。来看:线段树(SegmentTree)几乎是算法竞赛最常用的数据结构了,它主要用于维护区间信息(要求满足结合律)。与树状数组相比,它可以实现\(O(log⁡\n)\)的区间修改,......
  • delphi泛型模板编程
    delphi泛型模板编程泛型模板编程的关键:泛型作用体现在模板,体现在虚实之间相互转换,以虚概实,以实就虚。unitTxInfo;interfaceusesSystem.Types,System.Classes,System.SysUtils,Generics.Collections;typeTPeople=recordName:string;Age:str......
  • C++模板元编程(C++ template metaprogramming)
    实验平台:Win7,VS2013Community,GCC4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++模板给C++语言提供了元编程的能力,模板使C++编程变得异常灵活,能实现很多高级动态语言才有的特性(语法上可能比较丑陋,一些历史原因见下文)。普通用户对C++模板的使用可能不是很......
  • 线段树优化建图
    一个很好用的\(trick\)。我们通过例题CF786B为例。他需要我们支持点之间连边,点和区间之间连边,区间和点之间连边。支持最短路。如果我们暴力连边,显然最多是有\(n^2\)条边的。那怎么办呢,引入线段树分治。线段树分治在某些题中,我们可能会用\(v\tou\in[l,r]\)这种一个......
  • Destoon模板存放及调用规则
    一、模板存放及调用规则模板存放于系统template目录,template目录下的一个目录例如template/default/即为一套模板模板文件以.htm为扩展名,可直接存放于模板目录例如template/default/index.htm也可以存放于模板目录的子目录里例如template/default/member/index.htm在PHP......