线段树题目

news2025/10/21 4:05:18

目录

    • 题单
      • 线段树1
      • TJOI2009开关
      • 逆序对
      • 忠诚
      • 无聊的数列
      • 扶苏的问题
      • 线段树2
      • [COCI2010-2011#6]STEP
      • 三元上升子序列
      • 色板游戏
      • 小白逛公园
      • 方差
      • [yLOI2019]棠梨煎雪
      • 上帝造题的七分钟2/花神游历各国
      • [SCOI2010]序列操作
      • Points

题单

线段树1

区间相加,区间求和

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;

typedef long long LL;

int n, m;
int w[N];
struct Node {
    int l, r;
    LL sum, add;
}tr[N << 2];

void pushup(int u) {
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}

void pushdown(int u) {
    auto& root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
    if (root.add) {
        left.add += root.add, left.sum += (LL)(left.r - left.l + 1) * root.add;
        right.add += root.add, right.sum += (LL)(right.r - right.l + 1) * root.add;
        root.add = 0;
    }
}

void build(int u, int l, int r) {
    if (l == r) tr[u] = {l, r, w[l], 0};
    else {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        // 注意这里
        pushup(u);
    }
}

void modify(int u, int l, int r, int d) {
    if (l <= tr[u].l && r >= tr[u].r) {
        // [l, r]完全包含u对应的区间
        // 处理sum和懒标记
        tr[u].sum += (LL)d * (tr[u].r - tr[u].l + 1);
        tr[u].add += d;
    } else {
        // 注意这里
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, d);
        if (r > mid) modify(u << 1 | 1, l, r, d);
        // 注意这里
        pushup(u);
    }
}

LL query(int u, int l, int r) {
    if (l <= tr[u].l && r >= tr[u].r) return tr[u].sum;
    
    // 注意这里
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if (l <= mid) sum += query(u << 1, l, r);
    if (r > mid) sum += query(u << 1 | 1, l, r);
    return sum;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", w + i);
    
    build(1, 1, n);
    
    int op, l, r, d;
    
    while (m--) {
        scanf("%d", &op);
        if (op == 1) {
            scanf("%d%d%d", &l, &r, &d);
            modify(1, l, r, d);
        } else {
            scanf("%d%d", &l, &r);
            printf("%lld\n", query(1, l, r));
        }
    }
    return 0;
}

TJOI2009开关

一排灯初始是关闭的,每次可翻转一个区间的等的状态,每次询问一个区间内亮的等的个数。相当于是区间改状态,区间求和。
sum表示当前节点的开着的灯的个数,tag表示操作了多少次.

#include <bits/stdc++.h>
using namespace std;
 
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 42
#endif
 
const int N = 100010;
 
typedef long long LL;
 
int n, m;
int w[N];
struct Node {
    int l, r;
	// sum当前区间开着的灯的个数 tag标记:初始为0,操作一次变为1
    int sum, tag;
}tr[N << 2];
 
void pushup(int u) {
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
 
void pushdown(int u) {
    auto& root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
    if (root.tag) {
        left.tag ^=1, left.sum = (left.r - left.l + 1)- left.sum;
        right.tag ^= 1, right.sum = (right.r - right.l + 1) - right.sum;
        root.tag = 0;
    }
}
 
void build(int u, int l, int r) {
    if (l == r) tr[u] = {l, r, 0, 0};
    else {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        // 注意这里
        pushup(u);
    }
}
 
void modify(int u, int l, int r) {
    if (l <= tr[u].l && r >= tr[u].r) {
        // [l, r]完全包含u对应的区间
        // 处理sum和懒标记
        tr[u].sum = (tr[u].r - tr[u].l + 1) - tr[u].sum;
        tr[u].tag ^= 1;
    } else {
        // 注意这里
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r);
        if (r > mid) modify(u << 1 | 1, l, r);
        // 注意这里
        pushup(u);
    }
}
 
LL query(int u, int l, int r) {
    if (l <= tr[u].l && r >= tr[u].r) {
		// debug(tr[u].l, tr[u].r, tr[u].sum);
		return tr[u].sum;
	}
    
    // 注意这里
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if (l <= mid) sum += query(u << 1, l, r);
    if (r > mid) sum += query(u << 1 | 1, l, r);
    return sum;
}
 
int main() {
    scanf("%d%d", &n, &m);
    build(1, 1, n);
    
    int op, l, r, d;
    
    while (m--) {
        scanf("%d", &op);
        if (op == 0) {
            scanf("%d%d", &l, &r);
            modify(1, l, r);
        } else {
            scanf("%d%d", &l, &r);
            printf("%lld\n", query(1, l, r));
        }
    }
    return 0;
}
 

逆序对

忠诚

区间求最小值.

#include <bits/stdc++.h>
using namespace std;
 
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 42
#endif
 
typedef long long LL;

const int N = 200010;

struct Node
{
    int l, r;
    int v;  // 区间[l, r]中的最小值
}tr[N * 4];

int w[N];
void pushup(int u)  // 由子节点的信息,来计算父节点的信息
{
    tr[u].v = min(tr[u << 1].v, tr[u << 1 | 1].v);
}

void build(int u, int l, int r)
{
	
	if (l == r) tr[u] = {l, r, w[l]};
	else {
		tr[u] = {l, r};
		int mid = l + r >> 1;
		build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
		pushup(u);
	}
}

int query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].v; // 树中节点,已经被完全包含在[l, r]中了

    int mid = tr[u].l + tr[u].r >> 1;
    int v = INT_MAX;
    if (l <= mid) v = query(u << 1, l, r);
    if (r > mid) v = min(v, query(u << 1 | 1, l, r));

    return v;
}

// 本题不需要这个函数,这个函数是单点修改
void modify(int u, int x, int v)
{
    if (tr[u].l == x && tr[u].r == x) tr[u].v = v;
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        if (x <= mid) modify(u << 1, x, v);
        else modify(u << 1 | 1, x, v);
        pushup(u);
    }
}


int main()
{
    int m, n;
    scanf("%d%d", &m, &n);
	for (int i = 1; i <= m; i++) scanf("%d", w + i);
    build(1, 1, m);

    int x, y;
    while (n--)
    {
        scanf("%d%d", &x, &y);
		printf("%d ", query(1, x, y));
    }

    return 0;
}

无聊的数列

区间加等差数列。
转化为维护原序列的差分数列,那么区间 [ l , r ] [l,r] [l,r]加等差数列等价于在差分数列的[l]加首项, [ l + 1 , r ] [l+1, r] [l+1,r]加公差, [ r ] [r] [r]处减去末项. 转化为区间修改,区间求和的问题。

#include <bits/stdc++.h>
using namespace std;
 
const int N = 100010;
 
typedef long long LL;
 
int n, m;
int w[N];
struct Node {
    int l, r;
    LL sum, add;
}tr[N << 2];
 
void pushup(int u) {
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
 
void pushdown(int u) {
    auto& root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
    if (root.add) {
        left.add += root.add, left.sum += (LL)(left.r - left.l + 1) * root.add;
        right.add += root.add, right.sum += (LL)(right.r - right.l + 1) * root.add;
        root.add = 0;
    }
}
 
void build(int u, int l, int r) {
    if (l == r) tr[u] = {l, r, w[l], 0};
    else {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        // 注意这里
        pushup(u);
    }
}
 
void modify(int u, int l, int r, int d) {
    if (l <= tr[u].l && r >= tr[u].r) {
        // [l, r]完全包含u对应的区间
        // 处理sum和懒标记
        tr[u].sum += (LL)d * (tr[u].r - tr[u].l + 1);
        tr[u].add += d;
    } else {
        // 注意这里
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, d);
        if (r > mid) modify(u << 1 | 1, l, r, d);
        // 注意这里
        pushup(u);
    }
}
 
LL query(int u, int l, int r) {
    if (l <= tr[u].l && r >= tr[u].r) return tr[u].sum;
    
    // 注意这里
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if (l <= mid) sum += query(u << 1, l, r);
    if (r > mid) sum += query(u << 1 | 1, l, r);
    return sum;
}
 
int main() {
    scanf("%d%d", &n, &m);
	//原数组
    for (int i = 1; i <= n; i++) scanf("%d", w + i);
	// 差分数组
	for (int i = n; i > 1; i--) w[i] = w[i] - w[i - 1];
    
    build(1, 1, n);
    
    int op, l, r, k, d;
    
    while (m--) {
        scanf("%d", &op);
        if (op == 1) {
            scanf("%d%d%d%d", &l, &r, &k, &d);
			// 差分数组 w[l] += k
            modify(1, l, l, k);
			// 差分数组 [l+1, r] += d
            if (l + 1 <= r) modify(1, l + 1, r, d);
			// 差分数组 w[r+1]-=末项 也就是 k+d*(r-l)
            if (r < n) modify(1, r + 1, r + 1, -(k + 1LL * d * (r - l)));
        } else {
            scanf("%d", &r);
            printf("%lld\n", query(1, 1, r));
        }
    }
    return 0;
}
 

扶苏的问题

支持区间加,区间修改,询问区间最大值
做法:打两个标记

线段树2

支持区间加,区间乘,求区间和
做法:打两个标记

[COCI2010-2011#6]STEP

01序列,支持单点修改一个点,询问区间内的最长无相相邻数字连续串的长度

三元上升子序列

询问 i < j < k 且 a [ i ] < a [ j ] < a [ k ] i<j<k且a[i]<a[j]<a[k] i<j<ka[i]<a[j]<a[k]的序列个数

色板游戏

支持区间修改,询问区间内不同颜色个数。颜色个数 <= 30

小白逛公园

支持单点修改,询问区间内最长连续区间最大和

方差

支持区间加,询问区间平均数,询问区间方差

[yLOI2019]棠梨煎雪

m个01传,可能有?字符。支持单点修改,区间查询

上帝造题的七分钟2/花神游历各国

支持区间开平方,询问区间和

[SCOI2010]序列操作

给一个01序列,支持区间修改为0或1,区间取反,询问区间1的个数,询问区间最多连续1的个数

Points

二维坐标系,支持添加点,删除点,询问一个点最左边的点的坐标

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1234355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Serializable / Parcelable

Serializable 序列化,将对象转为二进制序列 Parcelable 不是序列化,属于进程间通信,不需要IO/操作,没有拷贝内存的操作, Object -> ShareMemory -> Object 不需要IO,使用内存共享等方式 Kotlin inline fun 内联函数 TCP协议将数据包拆分,进行发送,保证网络数据的可…

echarts折线图修改特定点的颜色

$.ajax({url:"/plc1672Ctrl/selectPage2.ctrl",dataType:"json",type:"POST",cache:false,data:{"serNo":$("#search").val().trim()},success:function(data){var list data.list;// x坐标var x new Array();// y坐标var…

ssm租房小程序-计算机毕设 附源码42196

SSM租房小程序 摘 要 本论文主要论述了如何使用SSM框架开发一个租房小程序&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构JAVA技术&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述租房小程序的当前背景以及系…

面试题:你怎么理解System.out.println() ?

文章目录 首先分析System源码out源码分析println分析拓展知识点 你如何理解System.out.println() ? 学了这么久的面向对象编程&#xff0c;那如何用一行代码体现呢&#xff1f; 如果你能自己读懂System.out.println()&#xff0c;就真正了解了Java面向对象编程的含义 面向对…

低代码服务商,中小型数字化软件服务商的新出路

数字化时代大背景下&#xff0c;企业信息化向数字化转型成为所有企业发展的必由之路&#xff0c;企业在对业务模式、流程、组织形式、信息技术等方面进行重新定义时&#xff0c;软件必然参与价值创造的全过程&#xff0c;这势必驱使软件成为推动数字化转型的“引擎”&#xff0…

debian 12 配置

1. 修改apt源 修改apt源为http版本 # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb http://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware # deb-src http://mirrors.tuna.tsinghua.edu.cn/d…

半导体业库存问题缓解,明年迎来良好转机 | 百能云芯

随着全球半导体产业今年产值预计将出现逾1成的衰退&#xff0c;市场一度陷入不确定性。然而&#xff0c;半导体厂商们对于供应链库存的有效去化表示乐观&#xff0c;预计将为明年带来健康的复苏。在各种因素交织的复杂情况下&#xff0c;半导体产业展现出逐步解决库存问题、迎来…

阿里云oss文件上传入门

先登录&#xff1a; 点击进入控制台 点击左上角导航栏按钮 搜索oss&#xff0c;点击进入 进入之后点击立即开通oss按钮&#xff0c;开通之后点击下图立即创建&#xff0c;弹出创建Bucket 填上Bucket名称&#xff0c;读写权限改为公共读。其他不变点击确定创建&#xff0c;完成…

Motion Plan之搜索算法笔记

背景&#xff1a; 16-18年做过一阵子无人驾驶&#xff0c;那时候痴迷于移动规划&#xff1b;然而当时可学习的资料非常少&#xff0c;网上的论文也不算太多。基本就是Darpa的几十篇无人越野几次比赛的文章&#xff0c;基本没有成系统的文章和代码讲解实现。所以对移动规划的认…

【深度学习实验】注意力机制(三):打分函数——加性注意力模型

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 理论介绍a. 认知神经学中的注意力b. 注意力机制 1. 注意力权重矩阵可视化&#xff08;矩阵热图&#xff09;2. 掩码Softmax 操作3. 打分函数——加性注意力模型1. 初始化2. 前向传播3. 内部组件…

SQL零基础入门教程,贼拉详细!贼拉简单! 速通数据库期末考!(十一)

COUNT() 计数函数 COUNT() 函数返回匹配指定条件的行数。 语法&#xff1a; 1.返回指定列的字段值条数 SELECT COUNT(column_name) FROM table_name;2.返回整表数据行条数 SELECT COUNT(*) FROM table_name;3.返回指定列去重后的字段值条数 SELECT COUNT(DISTINCT column_…

猫罐头牌子哪个好一点?精选5款口碑好的猫罐头推荐!

猫罐头牌子哪个好一点&#xff1f;选择猫罐头是十分重要的事情&#xff0c;千万不能将就。因为&#xff0c;好的猫罐头不仅可以营养丰富&#xff0c;水分充足&#xff0c;适口性好&#xff0c;还能易吸收。而一旦选择错误&#xff0c;不仅无法达到上述效果&#xff0c;还可能产…

服务号迁移到订阅号流程步骤

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;首先我们要知道服务号和订阅号有什么区别。服务号侧重于对用户进行服务&#xff0c;每月可推送4次&#xff0c;每次最多8篇文章&#xff0c;发送的消息直接显示在好友列表中。订阅号更侧重于信息传…

Stable Diffusion专场公开课

从SD原理、本地部署到其二次开发 分享时间&#xff1a;11月25日14&#xff1a;00-17&#xff1a;00 分享大纲 从扩散模型DDPM起步理解SD背后原理 SD的本地部署:在自己电脑上快速搭建、快速出图如何基于SD快速做二次开发(以七月的AIGC模特生成系统为例) 分享人简介 July&#…

通过AppLink把拼多多热门榜单商品同步至小红书

上篇说到AppLink当中定时调度方式如何配置&#xff0c;这次来演示一下&#xff0c;如何把热门榜单信息同步至小红书 1.拉取一个定时器作为触发动作&#xff0c;通过配置定时器调度时间将定时策略配置为每天执行一次 2.触发动作完成后通过好单库获取拼多多每日热门榜单&#xf…

循环链表3

插入函数——插入数据&#xff0c;在链表plsit的pos位置插入val数据元素 位置pos&#xff08;在无特别说明的情况下&#xff09;是从0开始计数的 要改变链表结构&#xff0c;就要依赖前驱&#xff0c;每个前驱的next存储着下一个数据结点的地址&#xff0c;也就是依靠前驱的ne…

笔尖笔帽检测3:Android实现笔尖笔帽检测算法(含源码 可是实时检测)

目录 1. 前言 2.笔尖笔帽检测方法 (1)Top-Down(自上而下)方法 (2)Bottom-Up(自下而上)方法&#xff1a; 3.笔尖笔帽关键点检测模型训练 4.笔尖笔帽关键点检测模型Android部署 &#xff08;1&#xff09; 将Pytorch模型转换ONNX模型 &#xff08;2&#xff09; 将ONNX模…

leetcode刷题日记:205. Isomorphic Strings(同构字符串)

205. Isomorphic Strings(同构字符串) 对于同构字符串来说也就是对于字符串s与字符串t&#xff0c;对于 s [ i ] s[i] s[i]可以映射到 t [ i ] t[i] t[i],同时对于任意 s [ k ] s [ i ] s[k]s[i] s[k]s[i]都有 s [ k ] s[k] s[k]映射到 t [ k ] t[k] t[k],则 t [ k ] t [ i …

海外IP代理科普——API代理是什么?怎么用?

随着互联网的不断发展&#xff0c;越来越多的企业开始使用API&#xff08;应用程序接口&#xff09;来实现数据的共享和交流。而在API使用中&#xff0c;海外代理IP也逐渐普及。那么&#xff0c;什么是API代理IP呢&#xff1f;它有什么作用&#xff1f;API接口有何用处&#xf…

Spring-IOC-@Value和@PropertySource

1、Book.java PropertySource(value"classpath:配置文件地址") 替代 <context:property-placeholder location"配置文件地址"/> Value("${book.bid}") Value("${book.bname}") Value("${book.price}") <bean id&…