//建树
int mi[100001];//树
void build(int k,int l,int r)//k为当前节点,l,r为当前节点所代表的区间
{
if(l==r)//叶节点
{
mi[k]=v;//赋最小值
return;
}
int mid=(l+r)/2;
build(k*2,l,mid);//左子树
build(k*2+1,mid+1,r);//右子树
mi[k]=min(mi[k*2],mi[k*2+1]);//从下往上更新
}
//区间查询(寻找最小值)
int query(int k,int l,int r,int x,int y)
{
if(y<l||x>r)return 1e9;//无交集
if(x<=l&&r<=y)return mi[k];//当前区间内
int mid=(l+r)/2;
return min(query(k*2,l,mid,x,y),query(k*2+1,mid+1,r,x,y));//分别处理左右区间
}
//单点修改
void change(int k,int l,int r,int x,int v)//x为修改值的位置,v为要修改为的值
{
if(r<x||l>x)return;//无交集
if(l==r&&l==x)//叶节点(到达要修改位置
{
mi[k]=v;
return;
}
int mid=(l+r)/2;
change(k*2+1,mid+1,r,x,v);//更新右子
change(k*2,l,mid,x,v);//更新左子
mi[k]=min(mi[k*2],mi[k*2+1]);//更新当前值
}
//单点修改区间查询模板题:1547区间和
#include<iostream>
#include<cstdio>
using namespace std;
long long mi[5000000],n,m;
long long query(int k,int l,int r,int x,int y)
{
if(y<l||x>r)return 0;
if(x<=l&&y>=r)return mi[k];
int mid=(l+r)/2;
return query(k*2,l,mid,x,y)+query(k*2+1,mid+1,r,x,y);
}
void change(int k,int l,int r,int x,int v)
{
if(r<x||l>x)return;
if(l==r&&l==x)
{
mi[k]+=v;
return;
}
int mid=(l+r)/2;
if(x>mid)change(k*2+1,mid+1,r,x,v);
else change(k*2,l,mid,x,v);
mi[k]=mi[k*2]+mi[k*2+1];
}
int main()
{
scanf("%lld%lld",&n,&m);
while(m--)
{
long long k,a,b;
scanf("%lld%lld%lld",&k,&a,&b);
if(k==0)
{
change(1,1,n,a,b);
}
if(k==1)
{
printf("%lld\n",query(1,1,n,a,b));
}
}
return 0;
}
线段树模版(单点修改,区间查询),例1.1547区间和
最新推荐文章于 2024-08-09 20:16:54 发布