题意:给定一个环形序列,进行在线操作,每次修改一个元素,输出环上的最大连续子列的和,但不能是完全序列。
分析:
如果不是环的话,只是一个序列,用线段树很方便求,所以将环从某一点切开成一个序列。
那么答案的最大连续和可能包含断点(换种想法,包含断点时的最大连续和即为 sum-区间最小的连续和)
1,若是所有的数都大于0,那么最大连续和(必须断开一个)即为 总和sum-最小非空连续和。
2,若是区间最小连续和小于0,那么答案就是MAX(区间最大连续和,sum-最小非空连续和)。即分为包含断点和不包含的比较。
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 #define ls rt<<1 9 #define rs rt<<1|1 10 #define lson l,m,ls 11 #define rson m+1,r,rs 12 #define mid (l+r)>>1 13 14 #define MAX(x,y) ((x)>(y)?(x):(y)) 15 #define MIN(x,y) ((x)>(y)?(y):(x)) 16 #define MAXN 100010 17 18 int N,M; 19 int a[MAXN]; 20 21 struct seg_tree 22 { 23 int l,r; 24 int lmax,rmax,summax; 25 int lmin,rmin,summin; 26 int sum; 27 }; 28 29 seg_tree tree[MAXN<<2]; 30 31 void PushUp(int rt) 32 { 33 tree[rt].sum=tree[ls].sum+tree[rs].sum; 34 35 tree[rt].lmax=MAX(tree[ls].lmax,tree[ls].sum+tree[rs].lmax); 36 tree[rt].rmax=MAX(tree[rs].rmax,tree[rs].sum+tree[ls].rmax); 37 tree[rt].summax=MAX(MAX(tree[ls].summax,tree[rs].summax),tree[ls].rmax+tree[rs].lmax); 38 39 40 tree[rt].lmin=MIN(tree[ls].lmin,tree[ls].sum+tree[rs].lmin); 41 tree[rt].rmin=MIN(tree[rs].rmin,tree[rs].sum+tree[ls].rmin); 42 tree[rt].summin=MIN(MIN(tree[ls].summin,tree[rs].summin),tree[ls].rmin+tree[rs].lmin); 43 44 } 45 46 void build(int l,int r,int rt) 47 { 48 if(l>r) return; 49 tree[rt].l=l; 50 tree[rt].r=r; 51 if(l==r) 52 { 53 tree[rt].sum=a[l]; 54 tree[rt].lmax=tree[rt].rmax=tree[rt].summax=a[l]; 55 tree[rt].lmin=tree[rt].rmin=tree[rt].summin=a[l]; 56 return; 57 } 58 int m=mid; 59 build(lson); 60 build(rson); 61 PushUp(rt); 62 } 63 64 void update(int pos,int val,int rt) 65 { 66 if(tree[rt].l==tree[rt].r && tree[rt].l==pos) 67 { 68 tree[rt].sum=val; 69 tree[rt].lmax=tree[rt].rmax=tree[rt].summax=val; 70 tree[rt].lmin=tree[rt].rmin=tree[rt].summin=val; 71 return; 72 } 73 74 int m=(tree[rt].l + tree[rt].r)>>1; 75 if(pos<=m) 76 update(pos,val,ls); 77 else 78 update(pos,val,rs); 79 PushUp(rt); 80 } 81 82 int main() 83 { 84 while(scanf("%d",&N)!=EOF) 85 { 86 for(int i=1;i<=N;i++) 87 scanf("%d",&a[i]); 88 build(1,N,1); 89 90 scanf("%d",&M); 91 int pos,val; 92 93 while(M--) 94 { 95 scanf("%d%d",&pos,&val); 96 update(pos,val,1); 97 98 if(tree[1].sum==tree[1].summax) 99 printf("%d\n",tree[1].sum-tree[1].summin); 100 else 101 printf("%d\n",MAX(tree[1].summax,tree[1].sum-tree[1].summin)); 102 } 103 } 104 return 0; 105 }