问题描述
有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操作的结果。
样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
数据规模与约定
对于20%的数据n <= 100,m <= 200。
对于50%的数据n <= 5000,m <= 5000。
对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。
利用线段树
把每一个节点都放在线段树中,进行存储
代码如下
#include<bits/stdc++.h>
using namespace std;
const int num=100000;
struct node{
int left,right,sum,max;
}tree[num*3];//设置左右节点,最大值,和
int length=0;
void settree(int p,int left,int right)//设置线段树
{
length++;
if(left==right)
{
tree[p].left=left;
tree[p].right=left;
tree[p].sum=left;
tree[p].max=left;
return ;
}//最低点
tree[p].left=left;
tree[p].right=right;
//左右子树
int mid=(left+right)/2;
settree(p*2,left,mid);settree(p*2+1,mid+1,right);//递归调用
tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
tree[p].max=tree[p*2].max>tree[p*2+1].max?tree[p*2].max:tree[p*2+1].max;
return;
}
void change(int p,int x,int y)//改变节点x的值为y
{
if(tree[p].left==tree[p].right)
{
tree[p].sum=y;
tree[p].max=y;
return ;
}//最低点
int mid=tree[p*2].right;
if(mid>=x)
change(p*2,x,y);
else
change(p*2+1,x,y);
//查找需要改变的位置
tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
tree[p].max=tree[p*2].max>tree[p*2+1].max?tree[p*2].max:tree[p*2+1].max;
return ;//和,最大值都改变
}
int find(int p,int x,int y,int choose)//查找最大值,求和
{
//cout<<"1"<<endl;
if(tree[p].left==x&&tree[p].right==y)
{
if(choose==2)
return tree[p].sum;
else
return tree[p].max;
}//最低点直接返回
int mid=tree[p*2].right;
if(mid>=y) return (find(p*2,x,y,choose));
else if(mid<x) return (find(p*2+1,x,y,choose));
else{
int le=find(p*2,x,mid,choose);
int ri=find(p*2+1,mid+1,y,choose);
if(choose==2) return le+ri;
else return (le>ri?le:ri);
}
//分三种情况
}
int main()
{
int n,m;
cin>>n>>m;
settree(1,1,n);
for(int i=1;i<=n;i++)
{
int ans;
cin>>ans;
if(ans!=i)
change(1,i,ans);
}//建立初始子树
while(m--)
{
int ans,q,r;
cin>>ans>>q>>r;
if(ans==1)
{
change(1,q,r);
// cout<<m<<endl;
}
if(ans==2)
{
cout<<find(1,q,r,2)<<endl;
}
if(ans==3)
{
cout<<find(1,q,r,3)<<endl;;
}
}
return 0;
}