线段树维护更多类型的信息

2024-08-31 12:04
文章标签 类型 信息 维护 线段

本文主要是介绍线段树维护更多类型的信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

P3870 [TJOI2009] 开关 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

sum维护一段区域的和;revers记录翻转懒信息;

lazy:灯泡翻转后个数就是之前不亮的个数,revers变为原来的反

#include <iostream>
using namespace std;
const int maxn = 100001;
int sum[maxn<<2];
bool revers[maxn << 2];
void up(int i) {sum[i] = sum[i << 1] + sum[i << 1 | 1];
}
void lazy(int i, int n) {sum[i] = n - sum[i];revers[i] = !revers[i];
}
void down(int i, int ln, int rn) {if (revers[i]) {lazy(i << 1, ln);lazy(i << 1 | 1, rn);revers[i] = false;}
}
void reverse(int jobl,int jobr,int l,int r,int i) {if (jobl <= l && jobr >= r)lazy(i, r - l + 1);else {int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if (jobl <= mid)reverse(jobl, jobr, l, mid, i << 1);if (jobr > mid)reverse(jobl, jobr, mid + 1, r, i << 1 | 1);up(i);}
}
int query(int jobl, int jobr, int l, int r, int i) {if (jobl <= l && jobr >= r)return sum[i];else {int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);int ans = 0;if (jobl <= mid)ans += query(jobl, jobr, l, mid, i << 1);if (jobr > mid)ans += query(jobl, jobr, mid + 1, r, i << 1 | 1);return ans;}
}
void build(int l, int r, int i) {if (l == r) sum[i] = 0;else {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);up(i);}revers[i] = false;
}
int main() {int n, m;cin >> n >> m;int a, b, c;int rem[maxn];int size = 0;build(1, n, 1);while (m--) {cin >> a >> b >> c;if (a == 0) {reverse(b, c, 1, n, 1);}else {rem[size++]=query(b, c, 1, n, 1);}}for (int i = 0; i < size; i++)cout << rem[i] << endl;return 0;
}

P2184 贪婪大陆 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

此题如果一段区域内不同的地雷总数是不能作为线段树信息维护的;所以此题维护的是一段区域内以某种地雷开头的位置数量和以某种地雷结尾的位置的数量两种信息。那么求一段区域 l - r 内地雷的总数,从1 - r地雷的开头数减去1 - l-1地雷的结尾数就是地雷的种类数。

此题是单点增加,所以不需要down和lazy操作

#include <iostream>
#include <vector>
using namespace std;
const int maxn = 100001;
int bomstart[maxn << 2];
int bomends[maxn << 2];
void up(int i) {bomstart[i] = bomstart[i << 1] + bomstart[i << 1 | 1];bomends[i] = bomends[i << 1] + bomends[i << 1 | 1];
}
void add(int jobt, int jobi, int l, int r, int i) {if (l == r) {if (jobt == 0)bomstart[i]++;elsebomends[i]++;}else {int mid = l + ((r - l) >> 1);if (mid >= jobi)add(jobt, jobi, l, mid, i << 1);elseadd(jobt, jobi, mid + 1, r, i << 1 | 1);up(i);}
}
int query(int jobt,int jobl, int jobr, int l, int r, int i) {if (jobl <= l && jobr >= r)return jobt == 0 ? bomstart[i] : bomends[i];else {int mid = l + ((r - l) >> 1);int ans = 0;if (mid >= jobl)ans += query(jobt, jobl, jobr, l, mid, i << 1);if (jobr > mid)ans += query(jobt, jobl, jobr,mid + 1, r, i << 1 | 1);return ans;}
}
void build(int l, int r, int i) {if (l < r) {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);}bomends[i] = 0;bomstart[i] = 0;
}
int main() {int n, m;cin >> n >> m;int a, b, c;vector<int>rem;while (m--) {cin >> a >> b >> c;if (a == 1) {add(0, b, 1, n, 1);add(1, c, 1, n, 1);}else {int s = query(0, 1, c, 1, n, 1);int e =b==1?0: query(1, 1, b-1, 1, n, 1);rem.push_back(s - e);}}for (auto i : rem)cout << i << endl;return 0;}

 P1438 无聊的数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

如果知道一组数的差分数组,在原数组的l - r范围上增加首项为k,公差为d的等差数组,只需要在l上增加k,l+1到r上增加d,r+1减去末项,从1到p求和即可得出原数组操作后p位置上的数。所以对差分信息维护线段树,做add操作和query操作即可

#include <iostream>
using namespace std;
const int maxn = 100001;
int diff[maxn];
long sum[maxn << 2];
long add[maxn << 2];
void up(int i) {sum[i] = sum[i << 1] + sum[i << 1 | 1];
}
void lazy(int i, int  n, int v) {add[i] += v;sum[i] += v * n;
}
void down(int i, int ln, int rn) {if (add[i] != 0) {lazy(i << 1, ln, add[i]);lazy(i << 1 | 1, rn, add[i]);add[i] = 0;}
}
void build(int l, int r, int i) {if (l == r)sum[i] = diff[l];else {int mid = l + ((r - l) >> 1);build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);up(i);}add[i] = 0;
}
void add1(int jobl, int jobr, int jobv, int l, int r, int i) {if (jobl <= l && jobr >= r) {lazy(i, r - l + 1, jobv);}else {int mid = l + ((r - l) >> 1);down(i, mid - l + 1, r - mid);if(mid>=jobl)add1(jobl, jobr, jobv, l, mid, i << 1);if(mid<jobr)add1(jobl, jobr, jobv, mid + 1, r, i << 1 | 1);up(i);}
}
long query(int jobl, int jobr, int l, int r, int i) {if (jobl <= l && jobr >= r)return sum[i];else {int mid = l + ((r - l) >> 1);long ans = 0;down(i, mid - l + 1, r - mid);if (jobl <= mid)ans += query(jobl, jobr, l, mid, i << 1);if (jobr > mid)ans += query(jobl, jobr, mid + 1, r, i << 1 | 1);return ans;}
}
int main() {int n, m;cin >> n >> m;int a;for (int i = 1,pre=0; i <= n; i++) {cin >> a;diff[i] = a - pre;pre = a;}build(1, n, 1);int b;int l, r, k, d;while (m--) {cin >> b;if (b == 1) {cin >> l >> r >> k >> d;int e = k + (r - l) * d;add1(l, l, k, 1, n, 1);if (l + 1 <= r)add1(l + 1, r, d, 1, n, 1);if (r < n)add1(r + 1, r + 1, -e, 1, n, 1);}else {int p;cin >> p;cout << query(1, p, 1, n, 1)<<endl;}}return 0;
}

P1471 方差 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

若求平均数和方差,只需要维护好累加和数组和平方和数组即可:累加和和平方和都可以成为线段树的维护信息。

add操作:累加和容易修改;平方和根据分析也可以O(1)修改

方差:拆开方差公式,用累加和和平方和就可以求出 

#include <cstdio>
using namespace std;const int MAXN = 100001;double arr[MAXN];
double sum1[MAXN << 2];
double sum2[MAXN << 2];
double addv[MAXN << 2];void up(int i) {sum1[i] = sum1[i << 1] + sum1[i << 1 | 1];sum2[i] = sum2[i << 1] + sum2[i << 1 | 1];
}void lazy(int i, double v, int n) {sum2[i] += sum1[i] * v * 2 + v * v * n;sum1[i] += v * n;addv[i] += v;
}void down(int i, int ln, int rn) {if (addv[i] != 0) {lazy(i << 1, addv[i], ln);lazy(i << 1 | 1, addv[i], rn);addv[i] = 0;}
}void build(int l, int r, int i) {if (l == r) {sum1[i] = arr[l];sum2[i] = arr[l] * arr[l];} else {int mid = (l + r) >> 1;build(l, mid, i << 1);build(mid + 1, r, i << 1 | 1);up(i);}addv[i] = 0;
}void add(int jobl, int jobr, double jobv, int l, int r, int i) {if (jobl <= l && r <= jobr) {lazy(i, jobv, r - l + 1);} else {int mid = (l + r) >> 1;down(i, mid - l + 1, r - mid);if (jobl <= mid) {add(jobl, jobr, jobv, l, mid, i << 1);}if (jobr > mid) {add(jobl, jobr, jobv, mid + 1, r, i << 1 | 1);}up(i);}
}double query(double *sum, int jobl, int jobr, int l, int r, int i) {if (jobl <= l && r <= jobr) {return sum[i];}int mid = (l + r) >> 1;down(i, mid - l + 1, r - mid);double ans = 0;if (jobl <= mid) {ans += query(sum, jobl, jobr, l, mid, i << 1);}if (jobr > mid) {ans += query(sum, jobl, jobr, mid + 1, r, i << 1 | 1);}return ans;
}int main() {int n, m;scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++) {scanf("%lf", &arr[i]);}build(1, n, 1);for (int i = 1; i <= m; i++) {int op, jobl, jobr;scanf("%d", &op);if (op == 1) {double jobv;scanf("%d %d %lf", &jobl, &jobr, &jobv);add(jobl, jobr, jobv, 1, n, 1);} else if (op == 2) {scanf("%d %d", &jobl, &jobr);double ans = query(sum1, jobl, jobr, 1, n, 1) / (jobr - jobl + 1);printf("%.4f\n", ans);} else {scanf("%d %d", &jobl, &jobr);double a = query(sum1, jobl, jobr, 1, n, 1);double b = query(sum2, jobl, jobr, 1, n, 1);double size = jobr - jobl + 1;double ans = b / size - (a / size) * (a / size);printf("%.4f\n", ans);}}return 0;
}

这篇关于线段树维护更多类型的信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1123848

相关文章

linux查找java项目日志查找报错信息方式

《linux查找java项目日志查找报错信息方式》日志查找定位步骤:进入项目,用tail-f实时跟踪日志,tail-n1000查看末尾1000行,grep搜索关键词或时间,vim内精准查找并高亮定位,... 目录日志查找定位在当前文件里找到报错消息总结日志查找定位1.cd 进入项目2.正常日志 和错误日

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

MySQL 索引简介及常见的索引类型有哪些

《MySQL索引简介及常见的索引类型有哪些》MySQL索引是加速数据检索的特殊结构,用于存储列值与位置信息,常见的索引类型包括:主键索引、唯一索引、普通索引、复合索引、全文索引和空间索引等,本文介绍... 目录什么是 mysql 的索引?常见的索引类型有哪些?总结性回答详细解释1. MySQL 索引的概念2

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录