hud 3308 LCIS 线段树 区间合并
题意:
Q a b 查询[a, b]区间的最长连续递增子序列的长度
U a b 将下表为a的元素更新为b
区间合并一般都有3个数组:区间最值,左区间最值和右区间最值
具体详见代码
#include <bits/stdc++.h> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int MAXN = 111111; int mx[MAXN<<2], a[MAXN]; int lmx[MAXN<<2], rmx[MAXN<<2]; void push_up(int rt, int l, int r) { lmx[rt] = lmx[rt<<1]; rmx[rt] = rmx[rt<<1|1]; mx[rt] = max(mx[rt<<1], mx[rt<<1|1]); int m = (l + r) >> 1; if(a[m] < a[m+1]) //保证是严格递增的 { if(lmx[rt] == m - l + 1) lmx[rt] += lmx[rt<<1|1]; if(rmx[rt] == r - m) rmx[rt] += rmx[rt<<1]; mx[rt] = max(mx[rt], rmx[rt<<1] + lmx[rt<<1|1]); } } void build(int l, int r, int rt) { if(l == r) { scanf("%d", &a[l]); mx[rt] = lmx[rt] = rmx[rt] = 1; return; } int m = (l + r) >> 1; build(lson); build(rson); push_up(rt, l, r); } void update(int p, int c, int l, int r, int rt) { if(l == r) { a[p] = c; return; } int m = (l + r) >> 1; if(m >= p) update(p, c, lson); else update(p, c, rson); push_up(rt, l, r); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) return mx[rt]; int m = (l + r) >> 1; int ret = 0; if(m >= L) ret = max(ret, query(L, R, lson)); if(m < R) ret = max(ret, query(L, R, rson)); if(a[m] < a[m+1]) //m-L+1是[L,m]的长度,R-m是[m,R]的长度 ret = max(ret, min(rmx[rt<<1], m-L+1) + min(lmx[rt<<1|1], R-m)); return ret; } int main() { // freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while(T--) { int n, m; scanf("%d%d", &n, &m); build(0, n-1, 1); while(m--) { char op[3]; int x, y; scanf("%s%d%d", op, &x, &y); if(op[0] == 'Q') printf("%d\n", query(x, y, 0, n-1, 1)); else update(x, y, 0, n-1, 1); } } return 0; }