加帕里公园的friends
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 131072/131072KB (Java/Others)Submit Status
我还有很多话想和她说,还有很多地方想和她去,把Kaban酱还给我!——Sabaru
薮猫酱为了从天蓝怪手里拯救小包,必须发现天蓝怪们的弱点所在。
具体来说,n只天蓝怪组成了一个序列A,每一只有一个战斗力数值Ai,
之后会发生m个事件,事件共有两种类型,有可能是
1、薮猫酱给你一个区间[a,b],要你输出max{Ap+Ap+1+…+Aq}(a≤p≤q≤b)
2、第pos只天蓝怪的战斗力变成了X
Input
第一行是两个整数n、m,第二行包含n个整数A1,A2,…,An,
接下来m行,每行三个整数,可能是
1ab,代表薮猫酱的一次询问;
2posX,代表某只天蓝怪战斗力的变化。
Output
对于每次询问,单独输出一行,代表答案。Sample input and output
Sample Input Sample Output5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
2
-1
Hint
1≤n≤500000,1≤m≤100000,
−1000≤Ai≤1000,
1≤a≤b≤n,
1≤pos≤n,
−1000≤X≤1000
Source
17暑假前集训-数据结构专题 By AutSky_JadeK
2017 UESTC Training for Data Structures
My Solution
题意:单点更新,区间查询最大子区间和。
线段树区间合并
每个节点维护四元组
int sum[4*MAXN], suml[4*MAXN], sumr[4*MAXN], ans[4*MAXN];
sum[Ind]表示该区间的和,suml[Ind]描述该区间从左端点开始的最大连续和,
sumr[Ind]表示从该区间右端点结束的最大连续和,ans[Ind]表示该区间的最大子区间和。
每次pushup的时候,刷新这四元组,
ans[Ind] = max(max(ans[Ind<<1], ans[Ind<<1|1]), sumr[Ind<<1] + suml[Ind<<1|1]);
suml[Ind] = max(suml[Ind<<1], sum[Ind<<1] + suml[Ind<<1|1]);
sumr[Ind] = max(sumr[Ind<<1|1], sumr[Ind<<1] + sum[Ind<<1|1]);
sum[Ind] = sum[Ind<<1] + sum[Ind<<1|1];
查询的时候,可以建立4个全局int findans, lans, rans, sumans;
每次查询到该最小区间即if(a <= l && r <= b)的时候刷新这个全局的四元组,
这样就不需要给查询函数设定返回值了,写起来比较方便,
即直接对该查询区间分成的子区间进行合并,具体见代码。
复杂度 O(nlogn)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 5e5 + 8;
const int INF = -2e9+8;
int sum[4*MAXN], suml[4*MAXN], sumr[4*MAXN], ans[4*MAXN];
int findans, lans, rans, sumans;
int sz;
inline void pushdown(int Ind)
{
;
}
inline void pushup(int Ind)
{
ans[Ind] = max(max(ans[Ind<<1], ans[Ind<<1|1]), sumr[Ind<<1] + suml[Ind<<1|1]);
suml[Ind] = max(suml[Ind<<1], sum[Ind<<1] + suml[Ind<<1|1]);
sumr[Ind] = max(sumr[Ind<<1|1], sumr[Ind<<1] + sum[Ind<<1|1]);
sum[Ind] = sum[Ind<<1] + sum[Ind<<1|1];
}
inline void _Query(int a, int b, int l, int r, int Ind){
if(a <= l && r <= b){
if(findans == INF){
findans = ans[Ind];
lans = suml[Ind];
rans = sumr[Ind];
sumans = sum[Ind];
return;
}
findans = max(max(findans, ans[Ind]), rans + suml[Ind]);
lans = max(lans, sumans + suml[Ind]);
rans = max(sumr[Ind], rans + sum[Ind]);
sumans = sumans + sum[Ind];
return;
}
int mid = (l + r) >> 1;
if(a <= mid) { _Query(a, b, l, mid, Ind<<1); }
if(b > mid) { _Query(a, b, mid + 1, r, Ind<<1|1);}
}
inline void _Modify(int a, int b, int l, int r, int Ind, int d){
if(a == l && b == r){
sum[Ind] = suml[Ind] = sumr[Ind] = ans[Ind] = d;
return;
}
int mid = (l + r) >> 1;
if(a <= mid){ _Modify(a, b, l, mid, Ind<<1, d); }
if(b > mid){ _Modify(a, b, mid + 1, r,Ind<<1|1, d); }
pushup(Ind);
}
inline void Query(int a, int b) {return _Query(a, b, 1, sz, 1);}
inline void Modify(int a, int b, int d){return _Modify(a, b, 1, sz, 1, d);}
int main()
{
#ifdef LOCAL
freopen("g.txt", "r", stdin);
//freopen("g.out", "w", stdout);
int T = 1;
while(T--){
#endif // LOCAL
//ios::sync_with_stdio(false); cin.tie(0);
int n, m, i, x, t, l, r;
scanf("%d%d", &n, &m);
sz = n;
for(i = 1; i <= n; i++){
scanf("%d", &x);
Modify(i, i, x);
}
while(m--){
scanf("%d%d%d", &t, &l, &r);
if(t == 1){
findans = lans = rans = sumans = INF;
Query(l, r);
printf("%d\n", findans);
}
else{
Modify(l, l, r);
}
}
#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}
Thank you!