题目:http://poj.org/problem?id=2750
题意:n个节点的环,在这个环中找到最大的连续字段和,,。。。
思路:建立一个线段树,每个节点有7个值,
sum这一段的总和;
lmin,lmax从左向右和最小、最大;
rmin,rmax从右向左和最小、最大;
amin,amax这一段的和最小、最大;
节点的更新为:push函数
1 void push(int w)//节点的更新 2 { 3 tree[w].sum=tree[L].sum+tree[R].sum; 4 tree[w].lmin=min(tree[L].lmin,tree[L].sum+tree[R].lmin); 5 tree[w].lmax=max(tree[L].lmax,tree[L].sum+tree[R].lmax); 6 7 tree[w].rmin=min(tree[R].rmin,tree[R].sum+tree[L].rmin); 8 tree[w].rmax=max(tree[R].rmax,tree[R].sum+tree[L].rmax); 9 10 tree[w].amin=min(min(tree[L].amin,tree[R].amin),tree[L].rmin+tree[R].lmin); 11 tree[w].amax=max(max(tree[L].amax,tree[R].amax),tree[L].rmax+tree[R].lmax); 12 }
注意:当n个数全为非负时,只能选n-1个;
因为是环,用所有数的和减去最小与最大值比较,找出大的就是所求值;
代码:
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define L w<<1 6 #define R w<<1|1 7 using namespace std; 8 const int maxn=100100; 9 10 struct node 11 { 12 int lmin,lmax; 13 int rmin,rmax; 14 int sum; 15 int amin,amax; 16 }tree[maxn*4]; 17 int map[maxn],p; 18 int max(int a,int b) 19 { 20 if(a>b) 21 return a; 22 else 23 return b; 24 } 25 int min(int a,int b) 26 { 27 if(a<b) 28 return a; 29 else 30 return b; 31 } 32 void push(int w)//节点的更新 33 { 34 tree[w].sum=tree[L].sum+tree[R].sum; 35 tree[w].lmin=min(tree[L].lmin,tree[L].sum+tree[R].lmin); 36 tree[w].lmax=max(tree[L].lmax,tree[L].sum+tree[R].lmax); 37 38 tree[w].rmin=min(tree[R].rmin,tree[R].sum+tree[L].rmin); 39 tree[w].rmax=max(tree[R].rmax,tree[R].sum+tree[L].rmax); 40 41 tree[w].amin=min(min(tree[L].amin,tree[R].amin),tree[L].rmin+tree[R].lmin); 42 tree[w].amax=max(max(tree[L].amax,tree[R].amax),tree[L].rmax+tree[R].lmax); 43 } 44 void build(int l,int r,int w) 45 { 46 if(l==r) 47 { 48 int u; 49 scanf("%d",&u); 50 tree[w].sum=u; 51 tree[w].lmin=tree[w].lmax=tree[w].rmin=tree[w].rmax=u; 52 tree[w].amin=tree[w].amax=u; 53 return ; 54 } 55 int m=(l+r)>>1; 56 build(l,m,L); 57 build(m+1,r,R); 58 push(w); 59 } 60 void update(int pos,int nnew,int l,int r,int w) 61 { 62 if(l==r) 63 { 64 tree[w].sum=nnew; 65 tree[w].lmin=tree[w].lmax=tree[w].rmin=tree[w].rmax=nnew; 66 tree[w].amin=tree[w].amax=nnew; 67 return ; 68 } 69 int m=(l+r)>>1; 70 if(pos<=m) 71 update(pos,nnew,l,m,L); 72 else 73 update(pos,nnew,m+1,r,R); 74 push(w); 75 } 76 int main() 77 { 78 int n; 79 while(scanf("%d",&n)!=EOF) 80 { 81 int i; 82 p=1; 83 build(1,n,1); 84 int Q; 85 int a,b; 86 scanf("%d",&Q); 87 for(i=0;i<Q;i++) 88 { 89 scanf("%d%d",&a,&b); 90 update(a,b,1,n,1); 91 int res; 92 if(tree[1].sum==tree[1].amax)//全为非负数的情况 93 res=tree[1].sum-tree[1].amin; 94 else 95 res=max(tree[1].amax,tree[1].sum-tree[1].amin);//因为是环 96 printf("%d ",res); 97 } 98 } 99 return 0; 100 }