今天又联系了一下线段树。
终于对线段树有了完整的了解。
查询和修改操作都是O(log n)级别的。
首次建树是O(n)。
举例的是:求某个区间的最小值。
input:
n
a0,a1,a2……an-1;
m
query x y
update x y
show x y
n为n个数
m为m次操作
query x y 查询 x-y之间的最小值;
update x y 修改 第x的数为y;
show x y 打印 x-y之间的所有数;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define INF 10000001
using namespace std;
int ql,qr,a[1000001];
int n,m,minv[10000001];
int query(int l,int r,int o)//查询操作
{
int m=(l+r)/2,ans=INF;
if(ql<=l&&qr>=r)return minv[o];
if(ql<=m)ans=min(ans,query(l,m,o*2));
if(qr>m)ans=min(ans,query(m+1,r,o*2+1));
return ans;
}
int update(int l,int r,int o,int in,int x)//更新某个值
{
int m=(l+r)>>1;
if(l<r)
{
int a,b;
a=minv[o*2+1],b=minv[o*2];
if(in>m)
a=update(m+1,r,o*2+1,in,x);
else
b=update(l,m,o*2,in,x);
minv[o]=min(a,b);
}
else
minv[o]=x;
return minv[o];
}
int build(int l,int r,int o)//建立线段树
{
int m=(l+r)>>1;
if(l<r)
minv[o]=min(build(l,m,o*2),build(m+1,r,o*2+1));
else
minv[o]=a[m];
return minv[o];
}
void show(int i,int j)//打印区间
{
while(i<j)
{
printf("%d ",a[i++]);
}
printf("\n");
}
int main()
{
while(cin>>n)
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
build(0,n-1,1);
char str[10];
int x,y;
cin>>m;
while(m--)
{
scanf("%s%d%d",str,&x,&y);
if(!strcmp(str,"query"))
{
ql=x-1,qr=y-1;
printf("%d\n",query(0,n-1,1));
}
else if(!strcmp(str,"update"))
{
a[x-1]=y;
update(0,n-1,1,x-1,y);
}
else if(!strcmp(str,"show"))
show(x-1,y);
}
}
}