博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线段树
阅读量:4880 次
发布时间:2019-06-11

本文共 2860 字,大约阅读时间需要 9 分钟。

一、基本概念

1.线段树是一颗二叉搜索树, 它储存的是区间的信息。

2 每个节点以结构体存储, 结构体包含以下几个信息:

区间左端点, 右端点;

3.线段树的基本思想:二分法

4:1、每个节点的左孩子区间范围为[l,mid],右孩子为[mid+1,r]

 

    2、对于结点k,左孩子结点为2*k,右孩子为2*k+1,这符合完全二叉树的性质

5.线段树可以用来查询区间的最值问题和和问题

 

#include
#include
using namespace std;struct Node { int l, r, w;//分别表示区间左右端点,w表示区间和} tree[4*1000+1];int x, y, ans;void build(int k, int l, int r) {
//建立树有值输入 tree[k].l = l; tree[k].r = r; if (tree[k].l == tree[k].r) { scanf("%d", &tree[k].w); return ; } int mid = (l + r) / 2; build(k*2, l, mid); build (k*2+1, mid+1, r); tree[k].w = tree[k*2].w + tree[k*2+1].w;//求区间的和}/*void build(int k, int l, int r) {//建立树无值输入 tree[k].l = l; tree[k].r = r; tree[k].w = 0; if (l < r) { int mid = (tree[k].l + tree[k].r) >> 1; build(k<<1, l, mid); build (k<<1|1, mid+1, r); }}*/void update(int k) {
//单点更新 if (tree[k].l == tree[k].r) { tree[k].w += y; return ; } int mid = (tree[k].l + tree[k].r)/2; if (x <= mid) update(k*2); else update(k*2+1); tree[k].w = tree[k*2].w + tree[k*2+1].w;//求区间的和}void updata1(int k, int x, int y, int w) {
//区间更新 if (tree[k].l >= x && tree[k].r <= y) { tree[k].w += w; return ; } int mid = (tree[k].l + tree[k].r) >> 1; if (y <= mid) updata1(k<<1, x, y, w); else if (x > mid) updata1(k<<1|1, x, y, w); else { updata1(k<<1, x, mid, w); updata1(k<<1|1, mid+1, y, w); }}void query(int k) {
//区间查询 if (tree[k].l >= x && tree[k].r <= y) { ans += tree[k].w; return ; } int mid = (tree[k].l + tree[k].r) / 2; if (x <= mid) query(k*2); if (y > mid) query(k*2+1);}int ask(int k, int x) {
//单点查询 if (tree[k].l == tree[k].r) { return tree[k].w; } else { int ans = tree[k].w; int mid = (tree[k].l + tree[k].r) >> 1; if (x <= mid) ans+=ask(k<<1, x); else ans+=ask(k<<1|1, x); return ans; }}int query1(int k) {
//最值查询 if (tree[k].l == tree[k].r) { return tree[k].w; } ans = 0; int mid = (tree[k].l + tree[k].r) / 2; if (x <= mid) ans = (ans,query(k*2)); else if (y > mid) ans = (ans ,query(k*2+1)); return ans;}int main() { int t; scanf("%d", &t); int count = 1; while (t--) { ans = 0; int n; scanf("%d", &n); build(1, 1, n); printf("Case %d:\n", count++); string str; while (cin>>str) { if (str == "End") break; scanf("%d%d", &x, &y); if (str == "Query") { int ans=query(1); printf("%d\n", ans); ans = 0; } else if (str == "Sub") { y = -y; update(1); } else { update(1); } } }}

 

转载于:https://www.cnblogs.com/a863886199/p/7786848.html

你可能感兴趣的文章
HTTP协议详解(三)
查看>>
Android零基础入门第84节:引入Fragment原来是这么回事
查看>>
解析SQL Server之任务调度
查看>>
参考资料地址
查看>>
08.路由规则中定义参数
查看>>
Pandas截取列部分字符,并据此修改另一列的数据
查看>>
java.lang.IllegalArgumentException
查看>>
【Spark】编程实战之模拟SparkRPC原理实现自定义RPC
查看>>
接口实现观察者模式
查看>>
四则运算完结篇
查看>>
Objective-C中的类目,延展,协议
查看>>
Python标准模块--Iterators和Generators
查看>>
Introduction Sockets to Programming in C using TCP/IP
查看>>
PHP 简单实现webSocket
查看>>
zookeeper部署搭建
查看>>
navigationController pop回之前控制器
查看>>
汇编语言实验一
查看>>
Web.config配置文件详解(新手必看)
查看>>
selenide总结
查看>>
selenium--控制浏览器和简单元素操作
查看>>