1. 程式人生 > 實用技巧 >SP1716 GSS3 - Can you answer these queries III 題解

SP1716 GSS3 - Can you answer these queries III 題解

Link

SP1716 GSS3 - Can you answer these queries III

Solve

看到題的第一想法就是線段樹,主要是要維護什麼東西。

因為一個答案和是否緊靠左右有關,我們就可以維護4個資訊,區間和\(sum\),區間內最大值\(max\),緊靠左端點的區間最大值\(lmax\),緊靠右端點的區間最大值\(rmax\)我們只需要修改一下上傳的資訊的\(pushup()\)即可。

c[x].sum=c[x<<1].sum+c[x<<1|1].sum;
c[x].lmax=max(c[x<<1].lmax,c[x<<1].sum+c[x<<1|1].lmax);
c[x].rmax=max(c[x<<1|1].rmax,c[x<<1|1].sum+c[x<<1].rmax);
c[x].max=max(c[x<<1].max,max(c[x<<1|1].max,c[x<<1].rmax+c[x<<1|1].lmax)); 

注意統計答案時也要遵循\(pushup\)的規律,如果\(l\)~\(mid\)\(mid\)+\(1\)~\(r\)都有分佈的話要開一個\(res\)統計一下,\(query\)的時候一定要注意。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=50005;
int N,Q,a[maxn];
struct node{
	int l,r,sum,lmax,rmax,max;
}c[maxn<<2];

inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
void pushup(int x){
	c[x].sum=c[x<<1].sum+c[x<<1|1].sum;
	c[x].lmax=max(c[x<<1].lmax,c[x<<1].sum+c[x<<1|1].lmax);
	c[x].rmax=max(c[x<<1|1].rmax,c[x<<1|1].sum+c[x<<1].rmax);
	c[x].max=max(c[x<<1].max,max(c[x<<1|1].max,c[x<<1].rmax+c[x<<1|1].lmax)); 
}
void build(int x,int l,int r){
	c[x].l=l,c[x].r=r;
	if(l==r){
		c[x].sum=c[x].lmax=c[x].rmax=c[x].max=a[l];
		return ;
	}
	int mid=(r-l>>1)+l;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	pushup(x);
}
void change(int x,int u,int v){
	if(c[x].l==c[x].r){
		c[x].lmax=c[x].rmax=c[x].max=c[x].sum=v;
		return ;
	}
	int mid=(c[x].r-c[x].l>>1)+c[x].l;
	if(u<=mid)change(x<<1,u,v);
	else change(x<<1|1,u,v);
	pushup(x);
}
node query(int x,int L,int R){
	if(L<=c[x].l&&c[x].r<=R)return c[x];
	int mid=(c[x].r-c[x].l>>1)+c[x].l;
	if(R<=mid)return query(x<<1,L,R);
	if(mid<L)return query(x<<1|1,L,R);
	node L_tree=query(x<<1,L,mid),R_tree=query(x<<1|1,mid+1,R),res;
	res.sum=L_tree.sum+R_tree.sum;
	res.lmax=max(L_tree.lmax,L_tree.sum+R_tree.lmax);
	res.rmax=max(R_tree.rmax,R_tree.sum+L_tree.rmax);
	res.max=max(L_tree.rmax+R_tree.lmax,max(L_tree.max,R_tree.max));
	return res;
}
int main(){
	freopen("SP1716.in","r",stdin);
	freopen("SP1716.out","w",stdout);
	N=read();
	for(int i=1;i<=N;i++)a[i]=read();
	Q=read();
	build(1,1,N);
	while(Q--){
		 int op=read(),x=read(),y=read();
		 if(op==0)change(1,x,y);
		 else printf("%d\n",query(1,x,y).max);
	}
	return 0;
}