1. 程式人生 > >SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III

maintain ref fin oid lse etc can [1] fix

題意:給定n個數a[1]~a[n],有q次操作。

操作 0 x y:把第a[x]修改為y;

操作 1 x y:詢問x到y的的最大子段和。

輸入:第一行:一個正整數n,表示有n個整數;

第二行:n個整數,表示數列;

第三行:一個正整數q,表示有q個詢問;

第4~q+3行:每行三個數p,x,y,表示三種操作。

輸出:對於每一個種類為1的詢問,輸出最大子段和。

輸入樣例:

4
1 2 3 4
4
1 1 3
0 3 -3
1 2 4
1 3 3

輸出樣例:

6
4
-3

解析:用線段樹進行維護,記錄下每一段的和(sum),最大子段和(maxv),最大前綴(prefix),最大後綴(suffix)。則

sum[o] = sum[o<<1] + sum[o<<1|1] ;

maxv[o] = max( max( maxv[o<<1] , maxv[o<<1|1] ) , suffix[o<<1] + prefix[o<<1|1] ) ;

prefix[o] = max( prefix[o<<1] , sum[o<<1] + prefix[o<<1|1] ) ;

suffix[o] = max( suffix[o<<1|1] , suffix[o<<1] + sum[o<<1|1] ) 。最好統計答案即可。

代碼如下:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define lc o<<1
 4 #define rc o<<1|1
 5 using namespace std;
 6 
 7 const int MAXN=50010;
 8 int n,a[MAXN],q,prefix[MAXN*4],suffix[MAXN*4],maxv[MAXN*4],sum[MAXN*4],ans,pre;
 9 
10 int read(void) {
11     char c; while (c=getchar(),(c<
0 || c>9) && c!=-); int x=0,y=1; 12 if (c==-) y=-1; else x=c-0; 13 while (c=getchar(),c>=0 && c<=9) x=x*10+c-0; return x*y; 14 } 15 16 void maintain(int o,int l,int r) { //維護 17 prefix[o]=max(prefix[lc],sum[lc]+prefix[rc]); 18 suffix[o]=max(suffix[rc],sum[rc]+suffix[lc]); 19 maxv[o]=max(maxv[lc],max(maxv[rc],suffix[lc]+prefix[rc])); 20 sum[o]=sum[lc]+sum[rc]; 21 } 22 23 void build(int o,int l,int r) { //建樹 24 if (l==r) { 25 prefix[o]=a[l]; 26 suffix[o]=a[l]; 27 maxv[o]=a[l]; 28 sum[o]=a[l]; 29 return; 30 } 31 int mid=l+r>>1; 32 build(lc,l,mid); build(rc,mid+1,r); 33 maintain(o,l,r); 34 } 35 36 void modify(int o,int l,int r,int p,int x) { //單點修改 37 if (l==r) { 38 prefix[o]=x; 39 suffix[o]=x; 40 maxv[o]=x; 41 sum[o]=x; 42 return; 43 } 44 int mid=l+r>>1; 45 if (p<=mid) modify(lc,l,mid,p,x); else modify(rc,mid+1,r,p,x); 46 maintain(o,l,r); 47 } 48 49 void query(int o,int l,int r,int ql,int qr) { //區間查詢 50 if (ql<=l && qr>=r) { //分三種情況考慮,統計答案 51 ans=max(ans,maxv[o]); 52 ans=max(ans,pre+prefix[o]); 53 pre=max(pre+sum[o],suffix[o]); 54 return; 55 } 56 int mid=l+r>>1; 57 if (ql<=mid) query(lc,l,mid,ql,qr); 58 if (qr>mid) query(rc,mid+1,r,ql,qr); 59 } 60 61 int main() { 62 n=read(); 63 for (int i=1;i<=n;++i) a[i]=read(); 64 build(1,1,n); 65 q=read(); 66 while (q--) { 67 int p=read(),x=read(),y=read(); 68 if (p) { 69 ans=pre=-2e9; 70 query(1,1,n,x,y); 71 printf("%d\n",ans); 72 } 73 else { 74 modify(1,1,n,x,y); 75 } 76 } 77 return 0; 78 }

SP1716 GSS3 - Can you answer these queries III