当前位置: 首页 > wzjs >正文

利川网站建设免费网站推广方式

利川网站建设,免费网站推广方式,用Html5做网站,企业名录查询软件【题目链接】 洛谷 P3374 【模板】树状数组 1 【题目考点】 1. 线段树 线段树(Segment tree)是一种用来维护区间信息的数据结构。 线段树中每个结点代表一个区间 根结点代表整体区间。 叶子结点代表长为1的单位区间。 对于线段树中的每一个分支结点 [ l , r ] [l, r] [l,r]…

【题目链接】

洛谷 P3374 【模板】树状数组 1

【题目考点】

1. 线段树

线段树(Segment tree)是一种用来维护区间信息的数据结构。
线段树中每个结点代表一个区间
根结点代表整体区间。
叶子结点代表长为1的单位区间。
对于线段树中的每一个分支结点 [ l , r ] [l, r] [l,r],m=(l+r)/2

  • 左孩子表示的区间为 [ l , m ] [l, m] [l,m]
  • 右孩子表示的区间为 [ m + 1 , r ] [m+1,r] [m+1,r]

线段树的设计思想为:分治思想

线段树的性质有:

  1. 线段树是平衡二叉树
  2. 线段树除去最后一层,是满二叉树。
  3. 区间长度为n的线段树的叶子结点数量为n。
  4. 区间长度为n的线段树的总结点数量为 2 n − 1 2n-1 2n1
  5. 任意两个结点或是包含关系,或者没有重叠部分。
  6. 区间长度为n的线段树的高度为 ⌈ log ⁡ 2 n ⌉ + 1 \lceil \log_2n \rceil+1 log2n+1
  7. 用顺序存储结构存储区间长为n的线段树,需要数组长度不超过4n-1。因此常把数组长度设为4n。
  8. 任意长为L的子区间都可以被分成不超过 2 log ⁡ 2 L 2\log_2L 2log2L个由线段树中结点表示的区间。

以上各性质的证明见:线段树相关性质证明

【解题思路】

首先线段树每个结点需要包含该结点表示的区间 [ l , r ] [l, r] [l,r],以及需要维护的该区间的加和。
使用树的顺序存储结构来保存线段树,表示线段树的数组是tree。
根据性质7,序列长度最大为 N N N时,数组长度需要开到 4 N 4N 4N

struct Node
{int l, r;//当前结点表示区间[l, r]long long val;//区间[l, r]的加和为val
} tree[4*N];

在树的顺序存储结构中,结点地址即为tree数组的下标。地址为 i i i的结点的左孩子的地址为 2 i 2i 2i,右孩子的地址为 2 i + 1 2i+1 2i+1
pushUp操作为使用孩子结点的值更新当前结点的值。本题中,孩子结点区间和的加和为当前结点表示的区间和。

void pushUp(int i)//更新地址为i的结点的值
{tree[i].val = tree[2*i].val+tree[2*i+1].val;
}

1. 建树

首先将数值序列输入到数组a。根据a序列建立线段树。
在建树过程中需要设置树中各个结点的区间、数值。
基本过程为:
先设置当前结点表示的区间。
如果当前结点为叶子结点,则设置该结点的值。
如果不是叶子结点,则先递归建立左子树,再递归建立右子树。
而后根据左右孩子的值确定当前结点的值。
建树的过程即为对线段树遍历的过程,根据性质4,线段树中总结点数量为 2 n − 1 2n-1 2n1,因此建树操作的时间复杂度为 O ( n ) O(n) O(n)

void build(int i, int l, int r)//构建根结点地址为i的表示区间[l, r]的线段树
{tree[i].l = l, tree[r].r = r;//设结点表示的区间if(l == r)//如果区间长度为1,该结点为叶子结点{tree[i].val = a[l];//原序列为a序列return;}int mid = (l+r)/2;build(2*i, l, mid);//递归构建左右子树build(2*i+1, mid+1, r);pushUp(i);//更新地址为i的结点的值
}

2. 单点修改

要使a序列中第x元素的值增加v,即完成a[x] += v,考虑线段树的变化。
首先在线段树中递归找到表示第x位置元素的叶子结点,将该结点的值修改,再不断向上回溯,回溯时使用孩子的值更新当前结点的值。
单点修改的函数递归调用次数与线段树高度成正比。根据性质6,线段树的高度为 O ( log ⁡ n ) O(\log n) O(logn)量级,因此线段树的单点修改操作的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

void update(int i, int x, long long v)//在根结点地址为i的线段树中,进行单点修改a[x] += v
{if(x < tree[i].l || x > tree[i].r) return;if(tree[i].l == tree[i].r)//如果i是叶子结点   {tree[i].val += v;return;}update(2*i, x, v);   update(2*i+1, x, v);pushUp(i);//更新地址为i的结点的值
}

3. 区间查询

要查询a序列给定区间 [ l , r ] [l, r] [l,r]中元素的加和,要做的是将 [ l , r ] [l, r] [l,r]区间划分为几个线段树中结点表示的区间,将这些区间的值加和。
要在某结点表示的区间中,返回 [ l , r ] [l, r] [l,r]中元素的加和:
首先判断当前结点表示的区间和 [ l , r ] [l, r] [l,r]是否有交集。如果没有交集则返回。
如果当前结点表示的区间完全被区间 [ l , r ] [l, r] [l,r]包含,则返回当前结点的值。
否则分别求出当前结点的两个子结点表示的区间中的且在 [ l , r ] [l, r] [l,r]中的元素的加和,将二者的加和返回。
每找到一个完全被 [ l , r ] [l, r] [l,r]包含的区间就返回。设 L = r − l + 1 L=r-l+1 L=rl+1,而 L L L最大可以达到 n n n。根据性质8,可知这样的区间有 2 log ⁡ 2 L 2\log_2L 2log2L个,是 O ( log ⁡ n ) O(\log n) O(logn)量级。区间查询访问到的结点构成了线段树的一个子树,该子树的叶子结点表示的就是区间 [ l , r ] [l, r] [l,r]被线段树划分成的各个区间。
该树的叶子结点数是 O ( log ⁡ n ) O(\log n) O(logn)的。
对于该树中度为1的结点,只有“左孩子表示的区间在 [ l , r ] [l, r] [l,r]外,右孩子表示的区间在 [ l , r ] [l, r] [l,r]内”,或“右孩子表示的区间在 [ l , r ] [l, r] [l,r]外,左孩子表示的区间在 [ l , r ] [l, r] [l,r]内”,只能最多在二叉树的左右两侧形成两条链,每条链的最大高度为 O ( log ⁡ n ) O(\log n) O(logn)

long long query(int i, int l, int r)
{//在根结点地址为i的线段树中,查询区间[l, r]中所有元素的和if(tree[i].r < l || tree[i].l > r)return 0; if(l <= tree[i].l && tree[i].r <= r)return tree[i].val;return query(2*i, l, r) + query(2*i+1, l, r);
}

【题解代码】

#include<bits/stdc++.h>
using namespace std;
#define N 500005
struct Node
{int val, l, r;
} tree[4*N];
int n, m, a[N];
void pushUp(int i)//更新tree[i]的值 
{tree[i].val = tree[2*i].val+tree[2*i+1].val;
}
void build(int i, int l, int r)//建树 O(n)
{tree[i].l = l, tree[i].r = r;if(l == r){tree[i].val = a[l];return;}int mid = (l+r)/2;build(2*i, l, mid);build(2*i+1, mid+1, r);pushUp(i);
}
void update(int i, int x, int v)//单点修改:a[x] += v O(logn)
{if(x < tree[i].l || x > tree[i].r)return;if(tree[i].l == tree[i].r){tree[i].val += v;return;}update(2*i, x, v);update(2*i+1, x, v);pushUp(i);
} 
int query(int i, int l, int r)//区间查询:a[l]+...+a[r] O(logn) 
{if(tree[i].r < l || tree[i].l > r)return 0;if(l <= tree[i].l && tree[i].r <= r)return tree[i].val;return query(2*i, l, r)+query(2*i+1, l, r);
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int op, x, k, y;cin >> n >> m;for(int i = 1; i <= n; ++i)cin >> a[i];build(1, 1, n);for(int i = 1; i <= m; ++i){cin >> op;if(op == 1){cin >> x >> k;update(1, x, k);} else{cin >> x >> y;cout << query(1, x, y) << '\n';}}return 0;
}
http://www.dtcms.com/wzjs/259223.html

相关文章:

  • 公司装修属于什么费用搜索引擎排名优化是什么意思
  • 做网页专题 应该关注哪些网站员工培训
  • 网站托管是什么意思百度有效点击软件
  • wordpress 地图xml生成关键词seo教程
  • 建站需要注意哪些中国舆情观察网
  • 做游戏能赚钱的网站营销手机都有什么功能啊
  • 南京做网站南京乐识好网站怎么收录
  • 天猫网站设计分析推广方案框架
  • 网站整体运营思路海外推广方案
  • 在建设部网站首页关键词排名哪里查
  • 上海制作网站公司百度人气榜
  • 做企业手机网站百度怎么推广自己的店铺
  • 韶关市建设局官方网站网络推广项目
  • 怎样用dw做新闻发布网站东莞网络公司排行榜
  • 电子商务网站建设个人总结怎么投放广告
  • 武威市住房和城乡建设局网站360识图
  • 驻马店市网站建设百度关键词搜索趋势
  • 网站备案登陆seo手机搜索快速排名
  • 做电脑系统的网站地域名网址查询
  • 智能客服系统建设广州专门做seo的公司
  • 电子商务网站建设asp sql 源码下载中国十大教育培训机构有哪些
  • 自己做的网站百度搜不到超级seo工具
  • 动态网站设计与制作seo长尾关键词排名
  • 做网站的需求分析十大营销模式
  • 网站只做优化seo图片优化的方法
  • 吉野家网站谁做的免费隐私网站推广
  • 怎么给公司做微网站竞价广告推广
  • 武汉专业建网站百度账号查询
  • 网站推广工做计划范本万网官网
  • 建立免费个人网站如何网络营销