题目链接:https://vjudge.net/problem/SPOJ-GSS3
Can you answer these queries III
You are given a sequence A of N (N <= 50000) integers between -10000 and 10000. On this sequence you have to apply M (M <= 50000) operations:
modify the i-th element in the sequence or for given x y print max{Ai + Ai+1 + .. + Aj | x<=i<=j<=y }.
Input
The first line of input contains an integer N. The following line contains N integers, representing the sequence A1..AN.
The third line contains an integer M. The next M lines contain the operations in following form:
0 x y: modify Ax into y (|y|<=10000).
1 x y: print max{Ai + Ai+1 + .. + Aj | x<=i<=j<=y }.
Output
For each query, print an integer as the problem required.
Example
Input:
4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3
Output:
6
4
-3
给你一个数组,两种操作,0是进行单点修改,1是查询给定区间的最大字段和
单点修改就是个zz,但是最大字段和有点头疼了就,因为无法避免两棵子树的邻接位置的子段求和,这个就让人很头疼,反正我愣是没想出来什么好法去整治他,只能去网上膜拜大神的blog
这个query函数写的就很妙了
void up(node &fa,node &lson,node &rson){//参数要注意
fa.sum=lson.sum+rson.sum;//和
fa.lmx=max(lson.lmx,lson.sum+rson.lmx);//父亲的左=max(左儿子的左,左儿子+右儿子的左)
fa.rmx=max(rson.rmx,rson.sum+lson.rmx);//父亲的右=max(右儿子的右,右儿子+左儿子的右)
fa.mx=max(max(lson.mx,rson.mx),lson.rmx+rson.lmx);//父亲的max=max(两个儿子的最大值或者中间的合并最大值)
}
node query(int k,int l,int r){//区间查询 [pl,pr]的最大子段和
if(l<=pp[k].l&&r>=pp[k].r)
return pp[k];//区间内部 直接返回
int mid=(pp[k].l+pp[k].r)>>1;
if(r<=mid)//区间左端
return query(k<<1,l,r);
if(l>mid)//区间右端
return query(k<<1|1,l,r);
//中间地带
node ls=query(k<<1,l,r);
node rs=query(k<<1|1,l,r);
node res;
up(res,ls,rs);//
return res;
}
函数的返回类型直接就是一个结构体,而且最厉害的是想到了中间使用新定义的结构体,这样就不会修改原子树的值,还有就是pushup函数也是想当配合,参数也是结构体,而且是&强制牵引型的,这也太机智了吧
我的脑袋瓜不够用啊 ,对于第一个解出来这道题的大佬 我只能Orz
这里的问题ko之后,完整的代码就是渣渣了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int mm=5e4+10;
struct node{
int l,r;
int lmx,rmx,mx,sum;
}pp[mm<<2];
int a[mm];
void up(node &fa,node &son,node &rson){//参数要注意
fa.sum=lson.sum+rson.sum;//和
fa.lmx=max(lson.lmx,lson.sum+rson.lmx);//父亲的左=max(左儿子的左,左儿子+右儿子的左)
fa.rmx=max(rson.rmx,rson.sum+lson.rmx);//父亲的右=max(右儿子的右,右儿子+左儿子的右)
fa.mx=max(max(lson.mx,rson.mx),lson.rmx+rson.lmx);//父亲的max=max(两个儿子的最大值或者中间的合并最大值)
}
void build(int k,int l,int r){
pp[k].l=l;
pp[k].r=r;
pp[k].lmx=pp[k].rmx=pp[k].mx=pp[k].sum=0;
if(l==r){
pp[k].lmx=pp[k].rmx=pp[k].sum=pp[k].mx=a[l];
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
up(pp[k],pp[k<<1],pp[k<<1|1]);
}
void change(int k,int x,int y){//单点修改 ,将x点的数改成 y
if(pp[k].l==pp[k].r){
pp[k].lmx=pp[k].rmx=pp[k].mx=pp[k].sum=y;
return ;
}
int mid=(pp[k].l+pp[k].r)>>1;
if(x<=mid)change(k<<1,x,y);
else change(k<<1|1,x,y);
up(pp[k],pp[k<<1],pp[k<<1|1]);
}
node query(int k,int l,int r){//区间查询 [pl,pr]的最大子段和
if(l<=pp[k].l&&r>=pp[k].r)
return pp[k];//区间内部 直接返回
int mid=(pp[k].l+pp[k].r)>>1;
if(r<=mid)//区间左端
return query(k<<1,l,r);
if(l>mid)//区间右端
return query(k<<1|1,l,r);
//中间地带
node ls=query(k<<1,l,r);
node rs=query(k<<1|1,l,r);
node res;
up(res,ls,rs);//
return res;
}
int n,m,op;
int x,y;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);
cin>>m;
while(m--){
cin>>op>>x>>y;
if(op==0)
change(1,x,y);
else
printf("%d\n",query(1,x,y).mx);
}
return 0;
}