大意:求区间最长连续上升序列。
思路:维护三个值。
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; }