大意:求区间最长连续上升序列。
思路:维护三个值。
1、左、右子树最长连续上升序列的最大值。
2、区间边界值,方便判断是否可以合并。
3、如果可以合并,有vr[lc] < vl[rc],则需记录左子树右边界可以到达的最左端,右子树左边界可以到达的最右端,求区间长度即可。
4、注意细节以及维护的值的更新条件。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 100010;
#define lc o*2
#define rc o*2+1
int n, m;
/*分别是左、右区间最值,
以及右边界能够到达的最左端,
左边界能够到达的最右端*/
int vl[maxn<<2], vr[maxn<<2], lmost[maxn<<2], rmost[maxn<<2];
int maxv[maxn<<2];
int addv[maxn<<2];
void pushdown(int o)
{
if(addv[o])
{
addv[lc] += addv[o];
addv[rc] += addv[o];
vl[lc] += addv[o], vr[lc] += addv[o];
vl[rc] += addv[o], vr[rc] += addv[o];
addv[o] = 0;
}
}
void pushup(int o, int M)
{
maxv[o] = max(maxv[lc], maxv[rc]);
vl[o] = vl[lc], vr[o] = vr[rc];
lmost[o] = lmost[rc], rmost[o] = rmost[lc];
if(vr[lc] < vl[rc])
{
maxv[o] = max(maxv[o], rmost[rc]-lmost[lc]+1);
if(rmost[o] >= M) rmost[o] = rmost[rc];
if(lmost[o] <= M+1) lmost[o] = lmost[lc];
}
}
void build(int o, int L, int R)
{
addv[o] = 0;
if(L == R)
{
scanf("%d", &vl[o]);
vr[o] = vl[o];
lmost[o] = rmost[o] = L;
maxv[o] = 1;
return ;
}
int M = L + (R-L)/2;
build(lc, L, M);
build(rc, M+1, R);
pushup(o, M);
}
void update(int o, int y1, int y2, int L, int R, int v)
{
if(y1 <= L && y2 >= R)
{
addv[o] += v;
vl[o] += v, vr[o] += v;
return ;
}
int M = L + (R-L)/2;
pushdown(o);
if(y1 <= M) update(lc, y1, y2, L, M, v);
if(y2 > M) update(rc, y1, y2, M+1, R, v);
pushup(o, M);
}
int query(int o, int y1, int y2, int L, int R)
{
if(y1 <= L && y2 >= R) return maxv[o];
int M = L + (R-L)/2, ans = 0;
if(y2 <= M) return query(lc, y1, y2, L, M);
if(y1 > M) return query(rc, y1, y2, M+1, R);
ans = max(query(lc, y1, y2, L, M), query(rc, y1, y2, M+1, R));
if(vr[lc] < vl[rc]) ans = max(ans, min(y2, rmost[rc]) - max(y1, lmost[lc])+1);
return ans;
}
void read_case()
{
scanf("%d%d", &n, &m);
build(1, 1, n);
}
void solve()
{
read_case();
char op[5];
int y1, y2, v;
while(m--)
{
scanf("%s%d%d", op, &y1, &y2);
if(op[0] == 'q')
{
int ans = query(1, y1, y2, 1, n);
printf("%d\n", ans);
}
else
{
scanf("%d", &v);
update(1, y1, y2, 1, n, v);
}
}
}
int main()
{
int T, times = 0;
scanf("%d", &T);
while(T--)
{
printf("Case #%d:\n", ++times);
solve();
}
return 0;
}