线段树(单点修改,区间查询)
引入
个正整数,编号从到,用,,表示。 修改:1.将第 个数增加 统计:1.编号从 到 的所有数之和为多少? 其中
方法如下(目前所学):
- 修改 —— ;循环求和 ——
- 差分:修改 个元素 ; 令 S[0]=0, S[k]=A[1..k] ,那么,A[L..R]的和就等于S[R]-S[L-1] ———
从上可以看出 方法一修改快,求和慢。 方法二求和快,修改慢。 那有没有一种结构,修改和求和都比较快呢?答案当然是
线段树的单点修改
1、分解区间
首先是讲原始子区间的分解,假定给定区间,只要 ,线段树就会把它继续分裂成两个区间。
首先计算 ,左子区间为,右子区间为,然后如果子区间不满足条件就递归分解。
2、
模板
#include<bits/stdc++.h>
using namespace std;
int read()
{
int s=0; char c=getchar();
for (;!isdigit(c);c=getchar());
for (;isdigit(c);c=getchar()) s=s*10+c-'0';
return s;
}
const int maxn=1e5;
int n,m;
struct Tree
{
int left,right,val=INT_MAX;
}tree[maxn*4+99];
void build(int k,int l,int r)
{
tree[k].left=l;
tree[k].right=r;
if(l==r)
{
tree[k].val=read();
return;
}
int mid=(l+r)/2;
int left=k*2,right=k*2+1;
build(left,l,mid);
build(right,mid+1,r);
tree[k].val=min(tree[left].val,tree[right].val);
}
void update(int o,int pos,int val)
{
if(tree[o].left==tree[o].right)
{
tree[o].val=val;
return;
}
int mid=(tree[o].left+tree[o].right)/2;
int left=o*2,right=o*2+1;
if(pos<=mid)
{
update(left,pos,val);
}
else
{
update(right,pos,val);
}
tree[o].val=min(tree[left].val,tree[right].val);
}
int query(int o,int L,int R)
{
if(L<=tree[o].left&&R>=tree[o].right)
{
return tree[o].val;
}
int mid=(tree[o].left+tree[o].right)/2;
int left=o*2,right=o*2+1;
int sum1=INT_MAX,sum2=INT_MAX;
if(L<=mid)
{
sum1=query(left,L,R);
}
if(R>mid)
{
sum2=query(right,L,R);
}
return min(sum1,sum2);
}
signed main()
{
cin>>n>>m;
build(1,1,n);
//for(int i=1;i<=n;i++)cout<<summ[i]<<" ";
//cout<<endl;
for(int i=1;i<=m;i++)
{
int q,l,r;
q=read();
l=read();
r=read();
if(q==2)
{
update(1,l,r);
}
else
{
cout<<query(1,l,r)<<" ";
}
}
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122198
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话