问题描述
有n个格子,从左到右放成一排,编号为1-n。
共有m次操作,有3种操作类型:
1.修改一个格子的权值,
2.求连续一段格子权值和,
3.求连续一段格子的最大值。
对于每个2、3操作输出你所求出的结果。
输入格式
第一行2个整数n,m。
接下来一行n个整数表示n个格子的初始权值。
接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。
输出格式
有若干行,行数等于p=2或3的操作总数。
每行1个整数,对应了每个p=2或3操作的结果。
解题思路
暴力求解!!!
直接求和,求最大值!!!
代码
#include
int arr[100000];
int sum(int x,int y)
{
int sum=0;
for(int i=x;i<=y;i++)
{
sum+=arr[i];
}
return sum;
}
int Max(int x,int y)
{
int res=arr[x];
for(int i=x;i<=y;i++)
{
if(arr[i]>res)res=arr[i];
}
return res;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&arr[i]);
}
for(int i=1;i<=m;i++)
{
int command,para1,para2;
scanf("%d%d%d",&command,¶1,¶2);
if(command==1)arr[para1]=para2;
if(command==2)
{
printf("%d\n",sum(para1,para2));
}
if(command==3)
{
printf("%d\n",Max(para1,para2));
}
}
return 0;
}
运行结果
竟然过了,过了。。。。
我惊呆了,题目上不是说要用线段树吗,暴力求解竟然能过。。。
不过,暴力不是我做这道题目的目的,还是去学习一下线段树吧!毕竟不是所有的测试系统都会对菜鸡这么友好。
线段树基础知识详解,强烈推荐!!!!
https://blog.csdn.net/huangzihaoal/article/details/81813454
(点击那句话也可以进入链接,这个博主讲的非常详细。)
线段树空间开辟的注意点:线段树的大小其实是4n左右的。
不然,最后测试用例上会因为索引越界而出现运行超时的错误,一定要注意!!!!
线段树求解代码
#include
struct node
{
int l,r,sum,Max,lazy;
node(){l=r=sum=Max=lazy=0;}
}a[400000];
int number[400000];//这里一定要是4n!!!
int Max(int a,int b){return a>b?a:b;}
inline void update(int k)//更新节点状态
{
a[k].sum=a[k*2].sum+a[k*2+1].sum;
a[k].Max=Max(a[k*2].Max,a[k*2+1].Max);
}
void build(int k,int l,int r)//建树
{
a[k].l=l,a[k].r=r;
if(l==r)
{
a[k].sum=number[l];
a[k].Max=number[l];
return;
}
int mid=(l+r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
update(k);
}
void change(int k,int x,int y)//改变节点
{
if(a[k].l==a[k].r){a[k].sum=y;a[k].Max=y;return;}
int mid=(a[k].l+a[k].r)/2;
if(x<=mid) change(k*2,x,y);
else change(k*2+1,x,y);
update(k);
}
int query(int k,int l,int r)//查询区间求和的值
{
if(a[k].l==l&&a[k].r==r) return a[k].sum;
int mid=(a[k].l+a[k].r)/2;
if(r<=mid)return query(k*2,l,r);
if(l>mid)return query(k*2+1,l,r);
return query(k*2,l,mid)+query(k*2+1,mid+1,r);
}
int queryMax(int k,int l,int r)//查询区间最大值
{
if(a[k].l==l&&a[k].r==r) return a[k].Max;
int mid=(a[k].l+a[k].r)/2;
if(r<=mid)return queryMax(k*2,l,r);
if(l>mid)return queryMax(k*2+1,l,r);
return Max(queryMax(k*2,l,mid),queryMax(k*2+1,mid+1,r));
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&number[i]);
}
build(1,1,n);
for(int i=1;i<=m;i++)
{
int command,para1,para2;
scanf("%d%d%d",&command,¶1,¶2);
if(command==1)
{
change(1,para1,para2);
}
if(command==2)
{
printf("%d\n",query(1,para1,para2));
}
if(command==3)
{
printf("%d\n",queryMax(1,para1,para2));
}
}
return 0;
}
运行结果
果然比暴力解法节省了不少的时间,算法真的神奇!!!