二维线段树【模板——给出对应注释】

2023-11-16

闲话少说,直接看注释反而会更容易读懂这段二维线段树的模板:


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define fur(i,x,y) for(i=x;i<=y;i++)
#define fdr(i,x,y) for(i=x;i>=y;i--)
#define Fur(i,x,y) for(ll i=x;i<=y;i++)
#define Fdr(x,y) for(ll i=x;i>=y;i--)
#define in2(x,y) in(x);in(y)
#define in3(x,y,z) in2(x,y);in(z)
#define in4(a,b,c,d) in2(a,b);in2(c,d)
#define clr(x,y) memset(x,y,sizeof(x))
#define cpy(x,y) memcpy(x,y,sizeof(x))
typedef long long ll;
using namespace std;
namespace fib{char b[300000]= {},*f=b;}
#define gc ((*fib::f)?(*(fib ::f++)):(fgets(fib::b,sizeof(fib::b),stdin)?(fib::f=fib::b,*(fib::f++)):-1))
inline void in(ll &x){x=0;char c;bool f=0;while((c=gc)>'9'||c<'0')if(c=='-')f=!f;x=c-48;while((c=gc)<='9'&&c>='0')x=x*10+c-48;if(f)x=-x;}
namespace fob{char b[300000]= {},*f=b,*g=b+300000-2;}
#define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0)
#define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0)
struct foce{~foce(){pob;fflush(stdout);}} _foce;
namespace ib{char b[100];}
inline void out(ll x){if(x==0){pc(48);return;}if(x<0){pc('-');x=-x;}char *s=ib::b;while(x) { *(++s)=x%10;x/=10; } while(s!=ib::b) pc((*(s--))+48);}
inline void outn(ll x){out(x);pc('\n');}
inline ll jdz(ll x){return x>0?x:-x;}
#define N 305
#define c1 (rt*4-2)     //左上子节点
#define c2 (rt*4-1)     //右上子节点
#define c3 (rt*4)       //左下子节点
#define c4 (rt*4+1)     //右下子节点
#define z1 x1,y1,mx,my
#define z2 x1,my+1,mx,y2
#define z3 mx+1,y1,x2,my
#define z4 mx+1,my+1,x2,y2
#define Z ll mx=(x1+x2)>>1,my=(y1+y2)>>1
#define U ll x1,ll y1,ll x2,ll y2,ll rt
#define pu s[rt]=s[c1]+s[c2]+s[c3]+s[c4]    //树的更新
ll s[N*N*4],laz[N*N*4],a[N][N],n,m,q,g[N*N*4];
bool b[N*N*4];
inline ll gs(ll x1,ll y1,ll x2,ll y2){return (jdz(x1-x2)+1)*(jdz(y1-y2)+1);}
inline void pd(ll rt,ll n1,ll n2,ll n3,ll n4)   //向下pushdown,n为其中的面积
{
    if(laz[rt])
    {
        ll t=laz[rt];
        s[c1]+=n1*t;
        s[c2]+=n2*t;
        s[c3]+=n3*t;
        s[c4]+=n4*t;
        laz[c1]+=t;
        laz[c2]+=t;
        laz[c3]+=t;
        laz[c4]+=t;
        laz[rt] = 0;
    }
}
inline void build(U)    //建树
{
    g[rt]=gs(x1,y1,x2,y2);  //面积
    if(x1==x2&&y1==y2){s[rt]=a[x1][y1]; return;}    //到底了,叶子结点的返回
    Z;
    build(z1,c1);   //左上节点是一直可以走的,跟求到的mid有关,所以左上是一定可以走的
    if(y1!=y2)build(z2,c2); //右上角的处理方式
    else b[c2]=1;       //右上角到底了
    if(x1!=x2) build(z3,c3);    //左下角是否可以建树
    else b[c3]=1;   //左下角到底了
    if(x1!=x2 && y1!=y2)build(z4,c4);   //此时才可以建立右下角(条件最为繁多)
    else b[c4]=1;   //右下角建立不了了
    pu;     //pushup()返回更新
}
inline void upd(ll X1,ll Y1,ll X2,ll Y2,ll v,U) //更新update()
{
    if(b[rt]) return;   //到叶子结点了,必须得返回
    if(X1<=x1&&Y1<=y1&&x2<=X2&&y2<=Y2){ s[rt]+=gs(x1,y1,x2,y2)*v; laz[rt]+=v; return; } //恰好是需要的区间,就直接返回即可
    Z;      //mid_x、mid_y的处理
    pd(rt,g[c1],g[c2],g[c3],g[c4]); //pushdown的是lazy标记
    if(X1<=mx&&Y1<=my)upd(X1,Y1,X2,Y2,v,z1,c1); //更新区间在左上角
    if(X1<=mx&&Y2>my)upd(X1,Y1,X2,Y2,v,z2,c2);  //更新区间在右上角
    if(X2>mx&&Y1<=my)upd(X1,Y1,X2,Y2,v,z3,c3);  //更新区间在左下角
    if(X2>mx&&Y2>my)upd(X1,Y1,X2,Y2,v,z4,c4);   //更新区间在右下角
    pu; //向上更新
}
inline ll qh(ll X1,ll Y1,ll X2,ll Y2,U) //查询函数
{
    if(b[rt]) return 0; //查到叶子节点了
    if(X1<=x1 && Y1<=y1 && x2<=X2 && y2<=Y2) return s[rt];
    Z,ans=0;    //初始化ans,列写mid_x, mid_y
    pd(rt,g[c1],g[c2],g[c3],g[c4]); //pushdown()lazy标记
    if(X1<=mx&&Y1<=my) ans+=qh(X1,Y1,X2,Y2,z1,c1);
    if(X1<=mx&&Y2>my) ans+=qh(X1,Y1,X2,Y2,z2,c2);
    if(X2>mx&&Y1<=my) ans+=qh(X1,Y1,X2,Y2,z3,c3);
    if(X2>mx&&Y2>my) ans+=qh(X1,Y1,X2,Y2,z4,c4);
    return ans;
}
int main(){
    in3(n,m,q);
    Fur(i,1,n)Fur(j,1,m)in(a[i][j]);
    build(1,1,n,m,1);
    ll p,x1,y1,x2,y2,v;
    while(q--){
        in(p);in4(x1,y1,x2,y2);
        if(p==1)outn(qh(x1,y1,x2,y2,1,1,n,m,1));
        else{in(v);upd(x1,y1,x2,y2,v,1,1,n,m,1);}
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二维线段树【模板——给出对应注释】 的相关文章

  • c#复制一个文件到指定文件夹

    c 复制一个文件到指定文件夹 path 指定文件夹From www uzhanbao com fileName指定文件的完整路径 public void CopyFile string path string fileName FileIn
  • mybatis-plus+druid配置多套数据源

    这里我使用的是mysql和postgresql进行配置 详细讲讲会遇到的问题 1 首先引入需要用到的依赖
  • 期货开户关于基本面量化

    一 库存 供求矛盾看库存 东西没有了 缺了 就会涨价 不缺 一般不会涨 所以 一定要注意库存 去库存快的品种 特别是库存低 价格低的品种 要重点关注 库存有一点要特别注意 要是 有效去库存 通过降价让下游买货 这种 去库存 不是根本 因为库

随机推荐

  • 【Python】fetchone()和fetchall()

    fetchone 返回单个的元组 也就是一条记录 row 如果没有结果 则返回 None cu execute select user password from user where user s name arr cur fetchon
  • 【多目标优化算法】多目标蚱蜢优化算法(Matlab代码实现)

    个人主页 研学社的博客 欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及详细文章讲解 1 概述
  • LeetCode 剑指 Offer 10- I. 斐波那契数列

    LeetCode 剑指 Offer 10 I 斐波那契数列 题目描述 写一个函数 输入 n 求斐波那契 Fibonacci 数列的第 n 项 即 F N 斐波那契数列的定义如下 F 0 0 F 1 1 F N F N 1 F N 2 其中
  • 用户画像统计标签(年龄段,消费周期,常用支付方式)

    年龄段 import bean HBaseMeta import org apache spark SparkContext import org apache spark sql 关联 不仅仅是一个相同的 可以 一个与两个之间 objec
  • 11.6.1:综合技巧练习 - 配置和测试网络

    实验ip分配如下 学习目标 创建 测试并配置整个实验网络 综合运用整套课程中学到的技巧 分析请求网页所涉及的事件 DNS ARP HTTP TCP IP Ethernet HDLC 分析在跟踪到 Web 服务器的路由时所涉及的事件 DNS
  • Nokogiri的使用 抓取csdn博客內容 rails

    Nokogiri 锯 使使用 Ruby 中的 XML 和 HTML 变得轻松而轻松 提供了一个明智的 易于理解的 API 阅读 编写 修改 和 查询 文档 它依赖于 libxml2 CRuby 和 xerces JRuby 等原生解析器 速
  • 光流法( Optical Flow Method)

    在计算机视觉中 光流法即可用于运动目标检测 也可以用于目标跟踪 本文主要介绍光流法在运动目标检测和目标跟踪中的区别与联系 1 光流与光流场 光流的概念最初是由 Gibson 于 1950 年首先提出来的 当人的眼睛观察运动物体时 物体的景象
  • 没有计算机网络地址怎么办,教大家电脑没有ip地址mac地址怎么办

    近日有关于电脑没有ip地址mac地址怎么办的问题受到了很多网友们的关注 大多数网友都想要知道电脑没有ip地址mac地址怎么办的具体情况 那么关于到电脑没有ip地址mac地址怎么办的相关信息 小编也是在网上进行了一系列的信息 那么接下来就由小
  • C#Replace

    在C 的字符串操作过程中 有时候需要替换字符串中的某个子字符串 此时就可以使用到字符串类自带的Replace方法来实现 Replace方法将查找到所有符合被替换的子字符串 然后将之全部替换为目标字符串 Replace方法有2个方法重载实现
  • 奇偶排序,双调排序,双调查找

    奇偶排序 奇偶排序是排序方法的一种 复杂度为O n 2 好处是可以利用处理器的并行 第一遍扫描a i a i 1 i为奇数 如果这两个次序不正确 就交换它们的次序 第二遍扫描偶数 双调排序 所谓双调序列 Bitonic Sequence 是
  • matlab 获取矩阵大小、行数、列数、元素总个数——size()/length()/numel()

    1 size size 获取数组的行数和列数 s size A 当只有一个输出参数时 返回一个行向量 该行向量的第一个元素时数组的行数 第二个元素是数组的列数 r c size A 当有两个输出参数时 size函数将数组的行数返回到第一个输
  • docker容器内开启22 ssh_Docker 添加容器SSH服务

    很多时候我们需要登陆到容器内部操作 此时我们就需要开启容器的SSH支持了 下面的小例子将具体介绍三种分配IP地址的方法 分别是pipworl分配 commit分配 Docker分配等 该系列文章只是本人的学习笔记 文章中的文字描述是 Lin
  • java_MD5加密源码

    package com lt util import java io UnsupportedEncodingException import java security MessageDigest import java security
  • 使用Kinect2作为Oculus游戏应用的输入设备

    注 文章写于2015年8月 眼下VR游戏Demo已经完结 所以把上一次预研的一些经验分享出来 希望对大家有所帮助 背景 初接触Oculus时 从网上下载了一大堆的Demo来体验 可是 操作体验大都比較差 特别是FPS类 这也让我们意识到 对
  • BMP转JPG(法二)RGB数据经过YUV交织

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家拍砖 源码下载地址 http download csdn net detail chenyujing1234 4441643 编译平台 VS20
  • ORACLE not available如何解决

    出现Oracle不可用可以一般情况下有两种办法解决 1 先关闭数据库 在打开数据库 SQL gt shutdown immediate SQL gt startup open 先用这种方式看看问题解决了没有 如果没有再用第二种办法试试 2
  • svn服务器 系统重装恢复吗,请教一下好不好把svn版本库还原到以前的版本?

    1 Linux系统安装svn服务 yuminstall subversion2 新建一个目录用于存储SVN所有文件 mkdir p cbroot svnserver cbweb3 在上面创建的文件夹中为项目project 1 创建一个版本仓
  • 操作系统 虚拟存储器的概念

    虚拟存储器 程序装入内存时可能会出现如下问题 程序太大 要求的空间超出了内存总容量 有大量作业要求运行 但内存不能容下所有作业 常规存储器管理方式的特征 一次性 要求作业全部装入内存才能运行 驻留性 许多不用或暂时不用的程序占用了大量内存空
  • linux命令strings

    linux命令strings 其man信息如下 strings 1 GNU Development Tools strings 1 NAME strings 显示文件中的可打印字符 总览 SYNOPSIS strings a all f p
  • 二维线段树【模板——给出对应注释】

    闲话少说 直接看注释反而会更容易读懂这段二维线段树的模板 include