https://www.spoj.com/problems/KGSS/
You are given a sequence A[1], A[2], ..., A[N] ( 0 ≤ A[i] ≤ 10^8 , 2 ≤ N ≤ 10^5 ). There are two types of operations and they are defined as follows:
Update:
ll n;
const int N = 1e5 + 10;
ll a[ N << 2 ];
ll place[ N << 2 ];
struct tree{
ll firstMax, secMax , sum;
};
tree t[ N << 2 ];
tree merge(tree foo, tree bar){
vi v;
v.pb(foo.firstMax);
v.pb(bar.firstMax);
v.pb(bar.secMax);
v.pb(foo.secMax);
sort(v.begin(), v.end());
tree ret;
ret.firstMax = v[3];
ret.secMax = v[2];
ret.sum = v[3] + v[2];
return ret;
}
void constructSegmentTree(ll low, ll high, ll sgmnt){
if(low == high){
t[sgmnt].firstMax = a[low];
t[sgmnt].secMax = 0;
t[sgmnt].sum = a[low];
place[low] = sgmnt;
return;
}
int mid = low + (high - low) / 2;
constructSegmentTree(low, mid, sgmnt*2+1);
constructSegmentTree(mid+1, high, sgmnt*2+2);
tree foo = t[sgmnt*2+1];
tree bar = t[sgmnt*2+2];
t[sgmnt] = merge(foo, bar);
}
void update(ll low, ll high, ll index, ll sgmnt){
ll v = place[index];
t[v].firstMax = t[v].sum = a[index];
if(v & 1)
v /= 2;
else{
v = v/2-1;
}
while(v >= 0){
t[v] = merge(t[v * 2 + 1], t[v * 2 + 2]);
if(v & 1)
v /= 2;
else{
v = v/2-1;
}
}
}
tree query(ll low, ll high, ll x, ll y, ll sgmnt){
if (x <= low && y >= high)
return t[sgmnt];
if(low > y || high < x){
tree temp;
temp.firstMax = temp.secMax = 0;
temp.sum = 0;
return temp;
}
int mid = low + (high - low) / 2;
if(y <= mid){
return query(low, mid, x, y, sgmnt * 2 + 1);
}
else if(x > mid){
return query(mid+1, high, x, y, sgmnt * 2 + 2);
}else{
return merge(query(low, mid, x, y, sgmnt * 2 + 1), query(mid+1, high, x, y, sgmnt * 2 + 2));
}
}
void solve(){
cin >> n;
ll i;
rep(i,n) {
cin >> a[i];
}
constructSegmentTree(0, n-1, 0);
ll q;
cin >> q;
while(q--){
char c;
cin >> c;
if(c == 'Q'){
// Query
ll x, y;
cin >> x >> y;
tree foo = query(0, n-1, x-1, y-1, 0);
cout << foo.sum << endl;
}else{
// UPDATE A VALUE
ll index, value;
cin >> index >> value;
index --;
a[index] = value;
update(0, n-1, index, 0);
}
}
}
https://blog.csdn.net/qq_36294146/article/details/79161490
You are given a sequence A[1], A[2], ..., A[N] ( 0 ≤ A[i] ≤ 10^8 , 2 ≤ N ≤ 10^5 ). There are two types of operations and they are defined as follows:
This will be indicated in the input by a 'U' followed by space and then two integers i and x.
U i x, 1 ≤ i ≤ N, and x, 0 ≤ x ≤ 10^8.
This operation sets the value of A[i] to x.
Query:
This will be indicated in the input by a 'Q' followed by a single space and then two integers i and j.
Q x y, 1 ≤ x < y ≤ N.
You must find i and j such that x ≤ i, j ≤ y and i != j, such that the sum A[i]+A[j] is maximized. Print the sum A[i]+A[j].
Input
The first line of input consists of an integer N representing the length of the sequence. Next line consists of N space separated integers A[i]. Next line contains an integer Q, Q ≤ 10^5, representing the number of operations. Next Q lines contain the operations.
Output
Output the maximum sum mentioned above, in a separate line, for each Query.
Example
Input: 5 1 2 3 4 5 6 Q 2 4 Q 2 5 U 1 6 Q 1 5 U 1 7 Q 1 5 Output: 7 9 11 12https://kartikkukreja.wordpress.com/2014/11/09/a-simple-approach-to-segment-trees/
This problem asks for the maximum pair sum in each subarray and also requires updates to individual array elements. As it turns out, we only need to store 2 things in each segment tree node:
- The maximum value in this range
- The second maximum value in this range
Hint : This problem asks for finding the maximum sum of 2 numbers in a given range.
So the largest and second largest element in given range would give us the maximum sum.
Structure of a node in our segment tree :
So the largest and second largest element in given range would give us the maximum sum.
Structure of a node in our segment tree :
1
2
3
4
5
| struct tree{ int firstMax; // largest element int secondMax; // second largest element int sum; // i used it in the following code but not required }; |
ll n;
const int N = 1e5 + 10;
ll a[ N << 2 ];
ll place[ N << 2 ];
struct tree{
ll firstMax, secMax , sum;
};
tree t[ N << 2 ];
tree merge(tree foo, tree bar){
vi v;
v.pb(foo.firstMax);
v.pb(bar.firstMax);
v.pb(bar.secMax);
v.pb(foo.secMax);
sort(v.begin(), v.end());
tree ret;
ret.firstMax = v[3];
ret.secMax = v[2];
ret.sum = v[3] + v[2];
return ret;
}
void constructSegmentTree(ll low, ll high, ll sgmnt){
if(low == high){
t[sgmnt].firstMax = a[low];
t[sgmnt].secMax = 0;
t[sgmnt].sum = a[low];
place[low] = sgmnt;
return;
}
int mid = low + (high - low) / 2;
constructSegmentTree(low, mid, sgmnt*2+1);
constructSegmentTree(mid+1, high, sgmnt*2+2);
tree foo = t[sgmnt*2+1];
tree bar = t[sgmnt*2+2];
t[sgmnt] = merge(foo, bar);
}
void update(ll low, ll high, ll index, ll sgmnt){
ll v = place[index];
t[v].firstMax = t[v].sum = a[index];
if(v & 1)
v /= 2;
else{
v = v/2-1;
}
while(v >= 0){
t[v] = merge(t[v * 2 + 1], t[v * 2 + 2]);
if(v & 1)
v /= 2;
else{
v = v/2-1;
}
}
}
tree query(ll low, ll high, ll x, ll y, ll sgmnt){
if (x <= low && y >= high)
return t[sgmnt];
if(low > y || high < x){
tree temp;
temp.firstMax = temp.secMax = 0;
temp.sum = 0;
return temp;
}
int mid = low + (high - low) / 2;
if(y <= mid){
return query(low, mid, x, y, sgmnt * 2 + 1);
}
else if(x > mid){
return query(mid+1, high, x, y, sgmnt * 2 + 2);
}else{
return merge(query(low, mid, x, y, sgmnt * 2 + 1), query(mid+1, high, x, y, sgmnt * 2 + 2));
}
}
void solve(){
cin >> n;
ll i;
rep(i,n) {
cin >> a[i];
}
constructSegmentTree(0, n-1, 0);
ll q;
cin >> q;
while(q--){
char c;
cin >> c;
if(c == 'Q'){
// Query
ll x, y;
cin >> x >> y;
tree foo = query(0, n-1, x-1, y-1, 0);
cout << foo.sum << endl;
}else{
// UPDATE A VALUE
ll index, value;
cin >> index >> value;
index --;
a[index] = value;
update(0, n-1, index, 0);
}
}
}
https://blog.csdn.net/qq_36294146/article/details/79161490