GSS1(SPOJ又死了先贴个luogu的)
线段树最大子段和裸题,不带修改
然而并不会猫树之类的东西
注意pushup和getans就好
1 #include<bits/stdc++.h>
2 #define MAXN 50001
3 using namespace std;
4 struct node{
5 int l , r , sum , lMax , rMax , midMax;
6 }Tree[MAXN << 2];
7 int a[MAXN] , rMax , allMax , N;
8
9 inline int max(int a , int b){
10 return a > b ? a : b;
11 }
12
13 void init(int dir , int l , int r){
14 Tree[dir].l = l;
15 Tree[dir].r = r;
16 if(l == r)
17 Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = a[l];
18 else{
19 init(dir << 1 , l , (l + r) >> 1);
20 init(dir << 1 | 1 , ((l + r) >> 1) + 1 , r);
21 Tree[dir].sum = Tree[dir << 1].sum + Tree[dir << 1 | 1].sum;
22 Tree[dir].lMax = max(Tree[dir << 1].lMax , Tree[dir << 1].sum + Tree[dir << 1 | 1].lMax);
23 Tree[dir].rMax = max(Tree[dir << 1 | 1].rMax , Tree[dir << 1 | 1].sum + Tree[dir << 1].rMax);
24 Tree[dir].midMax = max(max(Tree[dir << 1].midMax , Tree[dir << 1 | 1].midMax) , Tree[dir << 1].rMax + Tree[dir << 1 | 1].lMax);
25 }
26 }
27
28 void findMax(int dir , int l , int r){
29 if(Tree[dir].l >= l && Tree[dir].r <= r){
30 allMax = max(allMax , max(rMax + Tree[dir].lMax , Tree[dir].midMax));
31 rMax = max(max(Tree[dir].rMax , Tree[dir].sum + rMax) , 0);
32 return;
33 }
34 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
35 findMax(dir << 1 , l , r);
36 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
37 findMax(dir << 1 | 1 , l , r);
38 }
39
40 inline void work(int x , int y){
41 allMax = -0x7fffffff;
42 rMax = 0;
43 findMax(1 , x , y);
44 printf("%d\n" , allMax);
45 }
46
47 int main(){
48 scanf("%d" , &N);
49 for(int i = 1 ; i <= N ; i++)
50 scanf("%d" , a + i);
51 init(1 , 1 , N);
52 int T;
53 for(scanf("%d" , &T) ; T ; T--){
54 int a , b;
55 scanf("%d%d" , &a , &b);
56 work(a , b);
57 }
58 return 0;
59 }
带修改的GSS1
其实也没什么区别只是莫名代码长了很多
1 #include<bits/stdc++.h>
2 #define MAXN 50001
3 #define ll long long
4 using namespace std;
5 inline ll read(){
6 ll a = 0;
7 char c = getchar();
8 bool f = 0;
9 while(!isdigit(c)){
10 if(c == '-') f = 1;
11 c = getchar();
12 }
13 while(isdigit(c)) a = (a << 3) + (a << 1) + (c ^ '0') , c = getchar();
14 return f ? -a : a;
15 }
16
17 inline void print(ll x){
18 int num[21] , dirN = 0;
19 if(x < 0){
20 putchar('-');
21 x = -x;
22 }
23 while(x){
24 num[dirN++] = x % 10;
25 x /= 10;
26 }
27 if(dirN == 0) putchar('0');
28 while(dirN) putchar(num[--dirN] + 48);
29 putchar('\n');
30 }
31
32 struct node{
33 ll l , r , lMax , rMax , sum , midMax;
34 }Tree[MAXN << 2];
35 ll num[MAXN] , N , nowMaxLeft , nowMax;
36
37 inline ll max(ll a , ll b){return a > b ? a : b;}
38
39 void build(ll dir , ll l , ll r){
40 Tree[dir].l = l; Tree[dir].r = r;
41 if(l == r)
42 Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = num[l];
43 else{
44 build(dir << 1 , l , l + r >> 1);
45 build(dir << 1 | 1 , (l + r >> 1) + 1 , r);
46 Tree[dir].lMax = max(Tree[dir << 1].sum + Tree[dir << 1 | 1].lMax , Tree[dir << 1].lMax);
47 Tree[dir].rMax = max(Tree[dir << 1 | 1].sum + Tree[dir << 1].rMax , Tree[dir << 1 | 1].rMax);
48 Tree[dir].sum = Tree[dir << 1].sum + Tree[dir << 1 | 1].sum;
49 Tree[dir].midMax = max(Tree[dir << 1 | 1].lMax + Tree[dir << 1].rMax , max(Tree[dir << 1].midMax , Tree[dir << 1 | 1].midMax));
50 }
51 }
52
53 void change(ll dir , ll a , ll b){
54 if(Tree[dir].l == a && Tree[dir].r == a){
55 Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = b;
56 return;
57 }
58 if(a > Tree[dir].l + Tree[dir].r >> 1) change(dir << 1 | 1 , a , b);
59 else change(dir << 1 , a , b);
60 Tree[dir].lMax = max(Tree[dir << 1].sum + Tree[dir << 1 | 1].lMax , Tree[dir << 1].lMax);
61 Tree[dir].rMax = max(Tree[dir << 1 | 1].sum + Tree[dir << 1].rMax , Tree[dir << 1 | 1].rMax);
62 Tree[dir].sum = Tree[dir << 1].sum + Tree[dir << 1 | 1].sum;
63 Tree[dir].midMax = max(Tree[dir << 1 | 1].lMax + Tree[dir << 1].rMax , max(Tree[dir << 1].midMax , Tree[dir << 1 | 1].midMax));
64 }
65
66 void findMax(ll dir , ll a , ll b){
67 if(Tree[dir].l >= a && Tree[dir].r <= b){
68 nowMax = max(nowMax , max(max(nowMaxLeft , 0) + Tree[dir].lMax , Tree[dir].midMax));
69 nowMaxLeft = max(nowMaxLeft + Tree[dir].sum , Tree[dir].rMax);
70 return;
71 }
72 if(a <= Tree[dir].l + Tree[dir].r >> 1) findMax(dir << 1 , a , b);
73 if(b > Tree[dir].l + Tree[dir].r >> 1) findMax(dir << 1 | 1 , a , b);
74 }
75
76 int main(){
77 N = read();
78 for(register int i = 1 ; i <= N ; i++) num[i] = read();
79 build(1 , 1 , N);
80 register int a , b , M = read();
81 while(M--)
82 if(read() == 1){
83 a = read(); b = read();
84 nowMaxLeft = nowMax = -0x7f7f7f7f;
85 findMax(1 , a , b);
86 print(max(nowMax , nowMaxLeft));
87 }
88 else{
89 a = read(); b = read();
90 change(1 , a , b);
91 }
92 return 0;
93 }
话说这里有我的题解
设左区间为$[a,b]$,右区间为$[c,d]$,满足$b \geq c$
分类讨论:
①左端点在$[a,c)$,答案为$[a,c)$的最大后缀与$[c,d]$的最大前缀
②右端点在$(b,d]$,答案为$[a,b]$的最大后缀与$(b,d]$的最大前缀
③左右端点都在$[b,c]$,答案为$[b,c]$的最大子段和
1 #include<bits/stdc++.h>
2 #define MAXN 10001
3 using namespace std;
4
5 inline int max(int a , int b){
6 return a > b ? a : b;
7 }
8 inline int min(int a , int b){
9 return a < b ? a : b;
10 }
11
12 struct node{
13 int l , r , lMax , rMax , midMax , sum;
14 }Tree[MAXN << 2];
15 int a[MAXN] , N , lMax , rMax , allMax;
16
17 void init(int dir , int l , int r){
18 Tree[dir].l = l;
19 Tree[dir].r = r;
20 if(l == r)
21 Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = Tree[dir].sum = a[l];
22 else{
23 init(dir << 1 , l , (l + r) >> 1);
24 init(dir << 1 | 1 , ((l + r) >> 1) + 1 , r);
25 Tree[dir].sum = Tree[dir << 1].sum + Tree[dir << 1 | 1].sum;
26 Tree[dir].lMax = max(Tree[dir << 1].lMax , Tree[dir << 1].sum + Tree[dir << 1 | 1].lMax);
27 Tree[dir].rMax = max(Tree[dir << 1 | 1].rMax , Tree[dir << 1].rMax + Tree[dir << 1 | 1].sum);
28 Tree[dir].midMax = max(Tree[dir << 1].rMax + Tree[dir << 1 | 1].lMax , max(Tree[dir << 1].midMax , Tree[dir << 1 | 1].midMax));
29 }
30 }
31
32 int findSum(int dir , int l , int r){
33 if(Tree[dir].l >= l && Tree[dir].r <= r)
34 return Tree[dir].sum;
35 int sum = 0;
36 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
37 sum += findSum(dir << 1 , l , r);
38 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
39 sum += findSum(dir << 1 | 1 , l , r);
40 return sum;
41 }
42
43 void findRightMax(int dir , int l , int r){
44 if(Tree[dir].l >= l && Tree[dir].r <= r){
45 allMax = max(allMax , Tree[dir].rMax + rMax);
46 rMax += Tree[dir].sum;
47 return;
48 }
49 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
50 findRightMax(dir << 1 | 1 , l , r);
51 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
52 findRightMax(dir << 1 , l , r);
53 }
54
55 void findLeftMax(int dir , int l , int r){
56 if(Tree[dir].l >= l && Tree[dir].r <= r){
57 allMax = max(allMax , Tree[dir].lMax + lMax);
58 lMax += Tree[dir].sum;
59 return;
60 }
61 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
62 findLeftMax(dir << 1 , l , r);
63 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
64 findLeftMax(dir << 1 | 1 , l , r);
65 }
66
67 void findMax(int dir , int l , int r){
68 if(Tree[dir].l >= l && Tree[dir].r <= r){
69 allMax = max(allMax , max(Tree[dir].lMax + rMax , Tree[dir].midMax));
70 rMax = max(0 , max(Tree[dir].sum + rMax , Tree[dir].rMax));
71 return;
72 }
73 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
74 findMax(dir << 1 , l , r);
75 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
76 findMax(dir << 1 | 1 , l , r);
77 }
78
79 inline int getAns(int a , int b , int c , int d){
80 int t = 0;
81 if(b + 1 < c)
82 t += findSum(1 , b + 1 , c - 1);
83 if(a <= b){
84 allMax = -0x7fffffff;
85 rMax = 0;
86 findRightMax(1 , a , b);
87 t += allMax;
88 }
89 if(c <= d){
90 allMax = -0x7fffffff;
91 lMax = 0;
92 findLeftMax(1 , c , d);
93 t += allMax;
94 }
95 return t;
96 }
97
98 inline int work(int a , int b , int c , int d){
99 c = max(a , c);
100 b = min(b , d);
101 if(b < c)
102 return getAns(a , b , c , d);
103 else{
104 allMax = -0x7fffffff;
105 rMax = 0;
106 findMax(1 , c , b);
107 int t = allMax;
108 return max(max(getAns(a , c - 1 , c , d) , getAns(c , b , b + 1 , d)) , t);
109 }
110 }
111
112 int main(){
113 int T;
114 for(cin >> T ; T ; T--){
115 cin >> N;
116 for(int i = 1 ; i <= N ; i++)
117 cin >> a[i];
118 init(1 , 1 , N);
119 int M;
120 for(cin >> M ; M ; M--){
121 int a , b , c , d;
122 cin >> a >> b >> c >> d;
123 printf("%d\n" , work(a , b , c , d));
124 }
125 }
126 return 0;
127 }
GSS7
树剖+最大子段和
实际上也没什么区别只是莫名码量大了非常多
5.9K有史以来最长代码
1 #include<bits/stdc++.h>
2 #define MAXN 100001
3 using namespace std;
4 inline int read(){
5 int a = 0;
6 bool f = 0;
7 char c = getchar();
8 while(!isdigit(c)){
9 if(c == '-')
10 f = 1;
11 c = getchar();
12 }
13 while(isdigit(c)){
14 a = (a << 3) + (a << 1) + (c ^ '0');
15 c = getchar();
16 }
17 return f ? -a : a;
18 }
19 char output[12];
20 inline void print(int x){
21 int dirN = 11;
22 if(x == 0)
23 fwrite("0" , sizeof(char) , 1 , stdout);
24 else{
25 if(x < 0){
26 x = -x;
27 fwrite("-" , sizeof(char) , 1 , stdout);
28 }
29 while(x){
30 output[--dirN] = x % 10 + 48;
31 x /= 10;
32 }
33 fwrite(output + dirN , 1 , strlen(output + dirN) , stdout);
34 }
35 fwrite("\n" , 1 , 1 , stdout);
36 }
37
38 struct node{
39 int l , r , lMax , rMax , midMax , sum , mark;
40 }Tree[MAXN << 2];
41 struct Edge{
42 int end , upEd;
43 }Ed[MAXN << 1];
44 int val[MAXN] , head[MAXN] , size[MAXN] , son[MAXN] , fa[MAXN] , dep[MAXN];
45 int top[MAXN] , ind[MAXN] , rk[MAXN] , N , ts , cntEd , allMax , lMax , rMax;
46
47 inline void addEd(int a , int b){
48 Ed[++cntEd].end = b;
49 Ed[cntEd].upEd = head[a];
50 head[a] = cntEd;
51 }
52
53 void dfs1(int dir , int father){
54 size[dir] = 1;
55 dep[dir] = dep[fa[dir] = father] + 1;
56 for(int i = head[dir] ; i ; i = Ed[i].upEd)
57 if(!dep[Ed[i].end]){
58 dfs1(Ed[i].end , dir);
59 size[dir] += size[Ed[i].end];
60 if(size[son[dir]] < size[Ed[i].end])
61 son[dir] = Ed[i].end;
62 }
63 }
64
65 void dfs2(int dir , int t){
66 top[dir] = t;
67 rk[ind[dir] = ++ts] = dir;
68 if(!son[dir])
69 return;
70 dfs2(son[dir] , t);
71 for(int i = head[dir] ; i ; i = Ed[i].upEd)
72 if(Ed[i].end != son[dir] && Ed[i].end != fa[dir])
73 dfs2(Ed[i].end , Ed[i].end);
74 }
75
76 inline void pushup(int dir){
77 Tree[dir].lMax = max(Tree[dir << 1].lMax , Tree[dir << 1].sum + Tree[dir << 1 | 1].lMax);
78 Tree[dir].rMax = max(Tree[dir << 1 | 1].rMax , Tree[dir << 1].rMax + Tree[dir << 1 | 1].sum);
79 Tree[dir].sum = Tree[dir << 1].sum + Tree[dir << 1 | 1].sum;
80 Tree[dir].midMax = max(max(Tree[dir << 1].midMax , Tree[dir << 1 | 1].midMax) , Tree[dir << 1].rMax + Tree[dir << 1 | 1].lMax);
81 }
82
83 inline void pushdown(int dir){
84 if(Tree[dir].mark != -10001){
85 Tree[dir << 1].lMax = Tree[dir << 1].rMax = Tree[dir << 1].midMax = max(Tree[dir << 1].sum = Tree[dir].mark * (Tree[dir << 1].r - Tree[dir << 1].l + 1) , 0);
86 Tree[dir << 1 | 1].lMax = Tree[dir << 1 | 1].rMax = Tree[dir << 1 | 1].midMax = max(Tree[dir << 1 | 1].sum = Tree[dir].mark * (Tree[dir << 1 | 1].r - Tree[dir << 1 | 1].l + 1) , 0);
87 Tree[dir << 1].mark = Tree[dir << 1 | 1].mark = Tree[dir].mark;
88 Tree[dir].mark = -10001;
89 }
90 }
91
92 void init(int dir , int l , int r){
93 Tree[dir].l = l;
94 Tree[dir].r = r;
95 Tree[dir].mark = -10001;
96 if(l == r)
97 Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = max(Tree[dir].sum = val[rk[l]] , 0);
98 else{
99 init(dir << 1 , l , (l + r) >> 1);
100 init(dir << 1 | 1 , ((l + r) >> 1) + 1 , r);
101 pushup(dir);
102 }
103 }
104
105 void change(int dir , int l , int r , int val){
106 if(Tree[dir].l >= l && Tree[dir].r <= r){
107 Tree[dir].lMax = Tree[dir].rMax = Tree[dir].midMax = max(Tree[dir].sum = (Tree[dir].mark = val) * (Tree[dir].r - Tree[dir].l + 1) , 0);
108 return;
109 }
110 pushdown(dir);
111 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
112 change(dir << 1 , l , r , val);
113 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
114 change(dir << 1 | 1 , l , r , val);
115 pushup(dir);
116 }
117
118 void askLeft(int dir , int l , int r){
119 if(Tree[dir].l >= l && Tree[dir].r <= r){
120 allMax = max(allMax , max(lMax + Tree[dir].rMax , Tree[dir].midMax));
121 lMax = max(Tree[dir].lMax , Tree[dir].sum + lMax);
122 return;
123 }
124 pushdown(dir);
125 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
126 askLeft(dir << 1 | 1 , l , r);
127 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
128 askLeft(dir << 1 , l , r);
129 }
130
131 void askRight(int dir , int l , int r){
132 if(Tree[dir].l >= l && Tree[dir].r <= r){
133 allMax = max(allMax , max(rMax + Tree[dir].rMax , Tree[dir].midMax));
134 rMax = max(Tree[dir].lMax , Tree[dir].sum + rMax);
135 return;
136 }
137 pushdown(dir);
138 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
139 askRight(dir << 1 | 1 , l , r);
140 if(l <= (Tree[dir].l + Tree[dir].r) >> 1)
141 askRight(dir << 1 , l , r);
142 }
143
144 inline void work1(int l , int r , int val){
145 int tl = top[l] , tr = top[r];
146 while(tl != tr)
147 if(dep[tl] >= dep[tr]){
148 change(1 , ind[tl] , ind[l] , val);
149 tl = top[l = fa[tl]];
150 }
151 else{
152 change(1 , ind[tr] , ind[r] , val);
153 tr = top[r = fa[tr]];
154 }
155 if(ind[l] < ind[r])
156 change(1 , ind[l] , ind[r] , val);
157 else
158 change(1 , ind[r] , ind[l] , val);
159 }
160
161 inline void work2(int l , int r){
162 allMax = lMax = rMax = 0;
163 int tl = top[l] , tr = top[r];
164 while(tl != tr)
165 if(dep[tl] >= dep[tr]){
166 askLeft(1 , ind[tl] , ind[l]);
167 tl = top[l = fa[tl]];
168 }
169 else{
170 askRight(1 , ind[tr] , ind[r]);
171 tr = top[r = fa[tr]];
172 }
173 if(ind[l] < ind[r])
174 askRight(1 , ind[l] , ind[r]);
175 else
176 askLeft(1 , ind[r] , ind[l]);
177 print(max(allMax , lMax + rMax));
178 }
179
180 int main(){
181 N = read();
182 for(int i = 1 ; i <= N ; i++)
183 val[i] = read();
184 for(int i = 1 ; i < N ; i++){
185 int a = read() , b = read();
186 addEd(a , b);
187 addEd(b , a);
188 }
189 dfs1(1 , 0);
190 dfs2(1 , 1);
191 init(1 , 1 , N);
192 for(int Q = read() ; Q ; Q--){
193 int a = read() , b = read() , c = read();
194 if(a == 2)
195 work1(b , c , read());
196 else
197 work2(b , c);
198 }
199 return 0;
200 }