GSS6 - Can you answer these queries VI
GSS6 - Can you answer these queries VI
tree
Given a sequence A of N (N <= 100000) integers, you have to apply Q (Q <= 100000) operations:
Insert, delete, replace an element, find the maximum contiguous(non empty) sum in a given interval.
Input
The first line of the input contains an integer N.
The following line contains N integers, representing the starting
sequence A1..AN, (|Ai| <= 10000).
The third line contains an integer Q. The next Q lines contains the operations in following form:
I x y: insert element y at position x (between x - 1 and x).
D x : delete the element at position x.
R x y: replace element at position x with y.
Q x y: print max{Ai + Ai+1 + .. + Aj | x <= i <= j <= y}.
All given positions are valid, and given values are between -10000 and +10000.
The sequence will never be empty.
Output
For each "Q" operation, print an integer(one per line) as described above.
題目大意
在一個區間裡面求最大子段和。支援單點修改,插入刪除。
題解
序列問題還要插入刪除首先想到平衡樹(手動狗頭)
更新的思路就是用子樹的最大前後綴來更新。
特別注意子樹為空的情況,這個是大多數資料結構的邊界問題。
維護節點的最大子段和時要把自己考慮進去,左右子樹為空的情況,因為所有的維護的值都是不為空的,所以要單獨討論不取的情況。
只有一邊子樹+自己最優的情況一定要考慮進去
Code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define int long long
const int N = 2e5 + 11;
int n, a[N];
struct fhq{
struct node{
int ls, rs, key, sz, sum;
int val, max, lmax, rmax;
}t[N];
int tot, RT;
void push_up(int p){
int ls = t[p].ls, rs = t[p].rs;
int res = max(t[ls].max, t[rs].max);
res = max(max(t[p].val, res), t[ls].rmax + t[p].val + t[rs].lmax);
res = max(res, max(t[p].val + t[ls].rmax, t[p].val + t[rs].lmax));
t[p].max = res;
t[p].lmax = max(t[ls].lmax, max(t[ls].sum + t[p].val, t[ls].sum + t[p].val + t[rs].lmax));
t[p].rmax = max(t[rs].rmax, max(t[rs].sum + t[p].val, t[rs].sum + t[p].val + t[ls].rmax));
t[p].sz = t[ls].sz + t[rs].sz + 1;
t[p].sum = t[ls].sum + t[rs].sum + t[p].val;
}
int merge(int x, int y){
if(!x || !y)return x + y;
int p;
if(t[x].key < t[y].key){
p = x;
t[x].rs = merge(t[x].rs, y);
}
else {
p = y;
t[y].ls = merge(x, t[y].ls);
}
push_up(p);
return p;
}
void split(int &x, int &y, int p, int v){
if(!p){
x = y = 0;
return ;
}
int ls = t[p].ls, rs = t[p].rs;
if(t[ls].sz + 1 <= v){
x = p;
split(t[p].rs, y, rs, v - t[ls].sz - 1);
}
else {
y = p;
split(x, t[p].ls, ls, v);
}
push_up(p);
}
int new_node(int val){
t[++tot].val = val;
t[tot].sum = t[tot].lmax = t[tot].rmax = t[tot].max = val;
t[tot].key = rand();
t[tot].sz = 1;
return tot;
}
void insert(int pos, int v){
int x, y;
split(x, y, RT, pos);
int z = new_node(v);
RT = merge(x, merge(z, y));
}
void del(int pos){
int x, y, z;
split(x, y, RT, pos - 1);
split(y, z, y, 1);
RT = merge(x, z);
}
int query(int l, int r){
int x, y, z;
split(x, y, RT, l - 1);
split(y, z, y, r - l + 1);
int ans = t[y].max;
RT = merge(x, merge(y, z));
return ans;
}
void print(int p){
if(!p)return ;
print(t[p].ls);
printf("p=%d val=%d max=%d ls=%d rs=%d lmax=%d rmax=%d\n", p, t[p].val, t[p].max, t[p].ls, t[p].rs, t[p].lmax, t[p].rmax);
print(t[p].rs);
}
void init(){
t[0].max = t[0].lmax = t[0].rmax = t[0].val = -1e9;
}
}T;
int read(){
int x = 0;
char ch = getchar();
while(ch > '9' || ch < '0')ch = getchar();
while(ch >= '0' && ch <= '9')x = 10 * x + ch - 48, ch = getchar();
return x;
}
signed main(){
int Q;
cin>>n;
T.init();
for(int i = 1;i <= n; i++){
scanf("%lld", &a[i]);
T.insert(i, a[i]);
}
//printf("max=%d\n", T.t[T.RT].max);
cin>>Q;
while(Q--){
char s[11], fl;
int x, y;
scanf("%s", s + 1);
fl = s[1];
if(fl == 'I')scanf("%lld%lld", &x, &y), T.insert(x - 1, y);
if(fl == 'D')scanf("%lld", &x), T.del(x);
if(fl == 'R')scanf("%lld%lld", &x, &y), T.del(x), T.insert(x - 1, y);
if(fl == 'Q')scanf("%lld%lld", &x, &y), printf("%lld\n", T.query(x, y));
//T.print(T.RT);
//printf("max=%d\n", T.t[T.RT].max);
}
return 0;
}