问题描述
有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。
这次多了一个特性,就是多求了一个区间段的最大值,不分析了。
代码:
import java.util.Scanner;
class P//因为一个线段点不仅需要保存和值还要保存最大值,所以设了两个域值
{
int sum;
int max;
P(int sum,int max)
{
this.sum=sum;
this.max=max;
}
P(){}
}
public class Main
{
static P T[];
static Scanner sc;
public static void main(String[] args)
{
sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
T=new P[n<<2];
buildUp(1,1,n);//建树
int x[]=new int[3];
while((m--)>0)
{
for(int i=0;i<3;i++)
x[i]=sc.nextInt();
if(x[0]==1)
change(x[1],x[2],1,1,n);
else
if(x[0]==2)
System.out.println(querySum(x[1],x[2],1,1,n));
else
System.out.println(queryMax(x[1],x[2],1,1,n));
}
}
static void buildUp(int s,int l,int r)
{
if(l==r)
{
int a=sc.nextInt();
T[s]=new P(a,a);
return;
}
int m=(l+r)>>1;
buildUp(s<<1,l,m);
buildUp(s<<1|1,m+1,r);
T[s]=new P();
T[s].sum=T[s<<1].sum+T[s<<1|1].sum;
T[s].max=Math.max(T[s<<1].max, T[s<<1|1].max);//只是多了这行而已
}
static void change(int p,int c,int s,int l,int r)
{
if(l==r&&l==p)
{
T[s].max=c;
T[s].sum=c;
return;
}
int m=(l+r)>>1;
if(p<=m)
change(p,c,s<<1,l,m);
else
change(p,c,s<<1|1,m+1,r);
T[s].sum=T[s<<1].sum+T[s<<1|1].sum;
T[s].max=Math.max(T[s<<1].max, T[s<<1|1].max);//同样的和值和最大值都要变
}
static int querySum(int L,int R,int s,int l,int r)
{
if(L<=l&&r<=R)return T[s].sum;
int m=(l+r)>>1;
int ans=0;
if(m>=L)
ans+=querySum(L,R,s<<1,l,m);
if(m1|1,m+1,r);
return ans;//这里没变化
}
static int queryMax(int L,int R,int s,int l,int r)
{
if(L<=l&&r<=R)return T[s].max;
int m=(l+r)>>1;
if(R<=m)
return queryMax(L,R,s<<1,l,m);//进一步去缩小范围
if(mreturn queryMax(L,R,s<<1|1,m+1,r);
return Math.max(queryMax(L,R,s<<1,l,m), queryMax(L,R,s<<1|1,m+1,r));//如果m夹杂在R和L之间,那么我们就取他们的最大值,与求和函数还是有区别的
}
}