线段树 点更新版

/*
   程序功能:线段树区间求和求最值,点更新。
   time :2014/1/20
   code by wdsaid
*/
#include<stdio.h>

#define M 100050//区间长度
#define INF 1e9 //无穷大

int val[M];  //保存节点权值
int sum,max,min;//保存最终结果

struct node  //存储节点信息
{
	int l,r;
	int sum;
	int max;
	int min;
	int mid(){return (l+r)>>1;}//取中点用于二分查找
}T[M*4];

int Max(int a,int b)
{
	return a>b?a:b;
}
int Min(int a,int b)
{
	return a<b?a:b;
}

void Build(int l,int r,int root)//建树
{
	T[root].l=l;T[root].r=r;
	if(l==r)
	{
		T[root].sum=val[l];
		T[root].max=T[root].min=val[l];
		return;
	}
	int mid=T[root].mid();
	Build(l,mid,root<<1);
	Build(mid+1,r,root<<1|1);
	T[root].sum=T[root<<1].sum+T[root<<1|1].sum;
	T[root].max=Max(T[root<<1].max,T[root<<1|1].max);
	T[root].min=Min(T[root<<1].min,T[root<<1|1].min);
}

void Query(int l,int r,int root)//查询
{
	if(T[root].l==l&&T[root].r==r)
	{
		sum+=T[root].sum;
		max=Max(max,T[root].max);
		min=Min(min,T[root].min);
		return;
	}
	int mid=T[root].mid();
	if(r<=mid) Query(l,r,root<<1);
	else if(l>mid)Query(l,r,root<<1|1);
	else
	{
		Query(l,mid,root<<1);
		Query(mid+1,r,root<<1|1);
	}
}

void Modify(int root,int a,int d)//点更改
{
	if(a==T[root].l && a==T[root].r)
	{
		T[root].sum=T[root].max=T[root].min=d;
		return;
	}
	int mid=T[root].mid();
	if(a<=mid) Modify(root<<1,a,d);
	else Modify(root<<1|1,a,d);
	T[root].sum=T[root<<1].sum+T[root<<1|1].sum;
	T[root].max=Max(T[root<<1].max,T[root<<1|1].max);
	T[root].min=Min(T[root<<1].min,T[root<<1|1].min);
}

int main()
{
	int m,n,i,p,x,y;
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++) scanf("%d",&val[i]);
	Build(1,n,1);
	for(i=1;i<=m;i++)
	{
		max=-INF,min=INF,sum=0;
		scanf("%d %d %d",&p,&x,&y);
		switch(p)
		{
		case 1:Modify(1,x,y);break;
		case 2:Query(x,y,1);printf("%d\n",sum);break;
		case 3:Query(x,y,1);printf("%d\n",max);break;
		default:break;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值