你能回答这些问题吗-线段树

给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1、“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤ymaxx≤l≤r≤y{∑ri=lA[i]∑i=lrA[i]}。
2、“2 x y”,把 A[x] 改成 y。
对于每个查询指令,输出一个整数表示答案。
输入格式
第一行两个整数N,M。
第二行N个整数A[i]。
接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改。
输出格式
对于每个查询指令输出一个整数表示答案。
每个答案占一行。
数据范围
N≤500000,M≤100000N≤500000,M≤100000
输入样例:
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2

输出样例:
2
-1
思路:这道题典型的使用线段树,首先确定要存储的东西是什么,最大连续子段和必须存储然后判断能否通过这一点求出父节点的最大连续子段和,答案显然是不能的,父节点的最大连续子段和可能是左边儿子的最大连续子段和,又有可能是右儿子的最大连续子段和,还有可能是左儿子的最大后缀和加上右儿子的最大前缀和,所以还得存储最大前缀和和最大后缀和而最大前缀和又需要如何维护,父节点的最大前缀和可能等于左儿子的最大前缀和,也可能等于左儿子的总和加上右儿子的最大前缀和,所以这里就需要取一个最大值,同理,最大后缀和也是这样的,然后利用线段树的基本套路即可。
ac代码如下:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=500010;
int n,m;
int w[N];
struct Node{
 int l,r;
 int sum,lmax,rmax,tmax;
}tr[N*4];
void pushup(Node &u,Node &l,Node &r){
 u.sum=l.sum+r.sum;
 u.lmax=max(l.lmax,l.sum+r.lmax);
 u.rmax=max(r.rmax,r.sum+l.rmax);
 u.tmax=max(max(l.tmax,r.tmax),l.rmax+r.lmax);
}
void pushup(int u){
 pushup(tr[u],tr[u<<1],tr[u<<1 | 1]);
}
void build(int u,int l,int r){
 if(l==r)    tr[u]={l,r,w[r],w[r],w[r],w[r]};
 else{
  tr[u]={l,r};
  int mid=l+r>>1;
  build(u<<1,l,mid),build(u<<1 | 1,mid+1,r);
  pushup(u);
 }
}
int modify(int u,int x,int v){
 if(tr[u].l==x && tr[u].r==x)   tr[u]={x,x,v,v,v,v};
 else{
  
  int mid=tr[u].l+tr[u].r>>1;
  if(x<=mid)    modify(u<<1,x,v);
  else          modify(u<<1 |1 ,x,v);
  pushup(u);
 }
}
Node query(int u,int l,int r){
    if(tr[u].l>=l && tr[u].r<=r)   return tr[u];
 else{
  int mid=tr[u].l+tr[u].r>>1;
  if(r<=mid)    return query(u<<1,l,r);
  else if(l>mid)    return query(u<<1 | 1,l,r);
  else{
   Node left=query(u<<1,l,r);
   Node right=query(u<<1 |1 ,l,r);
   Node res;
   pushup(res,left,right);
   return res;
  }
 }    
}
int main(){
 scanf("%d%d",&n,&m);
 for(int i=1;i<=n;i++)    scanf("%d",&w[i]);
 build(1,1,n);
 int k,x,y;
 while(m--){
  scanf("%d%d%d",&k,&x,&y);
  if(k==1){
   if(x>y)  swap(x,y);
   printf("%d\n",query(1,x,y).tmax);
  }
  else      modify(1,x,y);
 }
} 
发布了29 篇原创文章 · 获赞 24 · 访问量 3669

猜你喜欢

转载自blog.csdn.net/qq_45772483/article/details/104315917