标签:
线段树在解决区间合并问题上还是很强力的,每个结点维护三个值:maxl, maxr, maxn,然后合并操作见pushup函数。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 50001; 7 int a[N]; 8 int sum[N]; 9 10 struct Node 11 { 12 int l, r; 13 int maxl, maxr, maxn; 14 } node[N << 2]; 15 16 void pushup( int i ) 17 { 18 int lc = i << 1, rc = lc | 1; 19 node[i].maxl = max( node[lc].maxl, sum[node[lc].r] - sum[node[lc].l - 1] + node[rc].maxl ); 20 node[i].maxr = max( node[rc].maxr, sum[node[rc].r] - sum[node[rc].l - 1] + node[lc].maxr ); 21 node[i].maxn = max( node[lc].maxn, node[rc].maxn ); 22 node[i].maxn = max( node[i].maxn, node[lc].maxr + node[rc].maxl ); 23 } 24 25 void build( int i, int l, int r ) 26 { 27 node[i].l = l, node[i].r = r; 28 if ( l == r ) 29 { 30 node[i].maxl = node[i].maxr = node[i].maxn = a[l]; 31 return ; 32 } 33 int lc = i << 1, rc = lc | 1, mid = ( l + r ) >> 1; 34 build( lc, l, mid ); 35 build( rc, mid + 1, r ); 36 pushup(i); 37 } 38 39 Node query( int i, int l, int r ) 40 { 41 if ( node[i].l == l && node[i].r == r ) 42 { 43 return node[i]; 44 } 45 int lc = i << 1, rc = lc | 1, mid = ( node[i].l + node[i].r ) >> 1; 46 if ( r <= mid ) 47 { 48 return query( lc, l, r ); 49 } 50 else if ( l > mid ) 51 { 52 return query( rc, l, r ); 53 } 54 else 55 { 56 Node ln = query( lc, l, mid ), rn = query( rc, mid + 1, r ), res; 57 res.maxl = max( ln.maxl, sum[mid] - sum[l - 1] + rn.maxl ); 58 res.maxr = max( rn.maxr, sum[r] - sum[mid] + ln.maxr ); 59 res.maxn = max( ln.maxn, rn.maxn ); 60 res.maxn = max( res.maxn, ln.maxr + rn.maxl ); 61 return res; 62 } 63 } 64 65 int main () 66 { 67 int n, m; 68 while ( scanf("%d", &n) != EOF ) 69 { 70 sum[0] = 0; 71 for ( int i = 1; i <= n; i++ ) 72 { 73 scanf("%d", a + i); 74 sum[i] = sum[i - 1] + a[i]; 75 } 76 build( 1, 1, n ); 77 scanf("%d", &m); 78 while ( m-- ) 79 { 80 int x, y; 81 scanf("%d%d", &x, &y); 82 Node tmp = query( 1, x, y ); 83 printf("%d\n", tmp.maxn); 84 } 85 } 86 return 0; 87 }
标签:
原文地址:http://www.cnblogs.com/huoxiayu/p/4690812.html