sicily 山海经 线段树实例

  1 #include <stdio.h>
2 #include <iostream>
3 using namespace std;
4 const int cmax = 100005;
5 const int minnum = -999999999;
6 int ans , s , x , posx , posy ;
7 struct Tnode
8 {
9
10 int maxs , sum , maxl , maxr ; // maxs为当前区间最大的序列和 , sum为当前区间的和 , maxl为当前区间左端点开始的最大序列和 , maxr
11 //为当前空间右端点结束的最大序列和
12 int posi , posj , posl , posr ; //posi为maxs的左端点 , posj为maxs的右端点 , posl为 maxl的右端点 , posr为maxr的左端点
13 int right , left ;//区间左端点 , 区间右端点
14 }tree[cmax * 4];
15 int temp , count = 0;
16 //从线段树的子节点往根节点更新信息
17 void PushUP(int p) {
18 tree[p].sum = tree[ 2 * p ].sum + tree[ 2* p + 1].sum;
19 tree[p].maxl = tree[ 2 * p ].maxl ;
20 tree[p].maxr = tree[ 2* p + 1] .maxr ;
21 tree[p].posl = tree[ 2* p].posl;
22 tree[p].posr = tree[ 2 * p + 1].posr;
23 int temp_sum;
24 temp_sum = tree[ 2* p ].sum + tree[ 2 * p + 1].maxl;
25 if ( temp_sum > tree[p].maxl )
26 {
27 tree[p].maxl = temp_sum;
28 tree[p].posl = tree[ 2 * p + 1 ] .posl;
29 }
30 temp_sum = tree[ 2 * p + 1].sum + tree[ 2 * p ].maxr ;
31 if ( temp_sum >= tree[p].maxr )
32 {
33 tree[p].maxr = temp_sum;
34 tree[p].posr = tree[ 2 * p ].posr;
35 }
36 tree[p].maxs = tree[ 2 * p ].maxs;
37 tree[p].posi = tree[ 2 * p].posi;
38 tree[p].posj = tree[ 2 * p].posj;
39 temp_sum = tree[ 2 * p].maxr + tree[ 2 * p +1 ].maxl;
40
41 if(temp_sum > tree[p].maxs || ( temp_sum == tree[p].maxs && tree[p*2].posr < tree[p].posi ) )
42 {
43 tree[p].maxs= temp_sum ;
44 tree[p].posi=tree[p*2].posr ;
45 tree[p].posj=tree[p*2+1].posl ;
46 }
47 if ( tree[p].maxs < tree[ 2 * p + 1].maxs )
48 {
49 tree[p].maxs = tree[ 2 * p + 1].maxs;
50 tree[p].posi = tree[ 2 * p + 1].posi;
51 tree[p].posj = tree[ 2 * p + 1].posj;
52 }
53 }
54 //建立线段树 , 初始化
55 void build( int p , int L , int R)
56 {
57 if ( L == R )
58 {
59 scanf("%d" , &temp);
60 tree[p].maxl = tree[p].maxr = tree[p].maxs = tree[p].sum = temp;
61 count++;
62 tree[p].posi = tree[p].posj = tree[p].posl = tree[p].posr = count;
63 tree[p].right = tree[p].left = L;
64 return ;
65 }
66 int mid = ( L + R ) /2 ;
67 build( p*2 , L , mid );
68 build( 2* p +1 , mid + 1 , R);
69 tree[p].right = R;
70 tree[p].left = L;
71 PushUP(p);//从叶子往父节点更新值 , 递归地从底层往上更新值
72
73 }
74 //线段树的查询操作
75 void query( int p , int L , int R)
76 {
77 if ( tree[p].left == L && tree[p].right == R)
78 {
79 if ( s + tree[p].maxl > ans )
80 {
81 ans = s + tree[p].maxl;
82 posx = x;
83 posy = tree[p].posl;
84 }
85
86 if ( tree[p].maxs > ans )
87 {
88 ans = tree[p].maxs;
89 posx= tree[p].posi;
90 posy = tree[p].posj;
91
92 }
93 int temp;
94 temp = s + tree[p].sum;
95 if ( temp > tree[p].maxr)
96 {
97 s = temp;
98 }
99 else
100 {
101 s = tree[p].maxr;
102 x = tree[p].posr;
103 }
104 return ;
105 }
106
107 int mid = ( tree[p].left + tree[p].right) / 2 ;
108 if ( R <= mid )
109 {
110 query( 2 * p , L , R);
111 }
112 else if ( L > mid )
113 {
114 query( 2 * p + 1 , L , R );
115 }
116 else
117 {
118 query( 2 * p , L , mid );
119 query( 2 * p + 1 , mid + 1 , R );
120 }
121 }
122 int main()
123 {
124 int n , m , value ;
125 int a , b;
126 scanf( "%d%d" , &n , &m);
127 build( 1 ,1 , n );
128 // cout << tree[6].maxs << tree[7].maxs << tree[8].maxs << tree[9].maxs;
129 // cout << tree[1].maxs << tree[2].maxs << tree[7].maxs;
130 while ( m --)
131 {
132 scanf("%d%d" , &a , &b );
133 s = 0 ;
134 x = a;
135 ans = minnum;
136 query( 1 , a , b );
137 printf("%d %d %d\n",posx,posy,ans);
138 }
139 return 0 ;
140 }
原文地址:https://www.cnblogs.com/lzhenf/p/2288583.html