UESTC_1425
更多和区间合并相关的线段树问题可以参考胡浩的博客:http://www.notonlysuccess.com/index.php/segment-tree-complete/。
这个题和HDU_3308很像,只不过要多处理一下区间加和的操作,为了能够方便的修改、获取左区间的右端点和右区间左端点的大小关系,可以用两个标记lx[]、rx[]分别表示当前区间左端点以及右端点的值。
#include<stdio.h> #include<string.h> #define MAXD 100010 int N, Q, a[MAXD], lc[4 * MAXD], rc[4 * MAXD], lx[4 * MAXD], rx[4 * MAXD], mc[4 * MAXD], add[4 * MAXD]; int getmax(int x, int y) { return x > y ? x : y; } void update(int cur, int x, int y) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; mc[cur] = getmax(mc[ls], mc[rs]); lc[cur] = lc[ls], rc[cur] = rc[rs]; if(rx[ls] < lx[rs]) { if(rc[ls] + lc[rs] > mc[cur]) mc[cur] = rc[ls] + lc[rs]; if(lc[ls] == mid - x + 1) lc[cur] += lc[rs]; if(rc[rs] == y - mid) rc[cur] += rc[ls]; } lx[cur] = lx[ls], rx[cur] = rx[rs]; } void pushdown(int cur) { int ls = cur << 1, rs = (cur << 1) | 1; if(add[cur]) { add[ls] += add[cur], add[rs] += add[cur]; lx[ls] += add[cur], rx[ls] += add[cur]; lx[rs] += add[cur], rx[rs] += add[cur]; add[cur] = 0; } } void build(int cur, int x, int y) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; add[cur] = 0; if(x == y) { mc[cur] = lc[cur] = rc[cur] = 1; lx[cur] = rx[cur] = a[x]; return ; } build(ls, x, mid); build(rs, mid + 1, y); update(cur, x, y); } void init() { int i, j, k; scanf("%d%d", &N, &Q); for(i = 1; i <= N; i ++) scanf("%d", &a[i]); build(1, 1, N); } int query(int cur, int x, int y, int s, int t, int fa, int &ans) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x >= s && y <= t) { if(mc[cur] > ans) ans = mc[cur]; return fa == -1 ? lc[cur] : rc[cur]; } pushdown(cur); if(mid >= t) return query(ls, x, mid, s, t, -1, ans); else if(mid + 1 <= s) return query(rs, mid + 1, y, s, t, 1, ans); else { int ln = query(ls, x, mid, s, t, 1, ans), rn = query(rs, mid + 1, y, s, t, -1, ans); if(rx[ls] < lx[rs]) { if(ln + rn > ans) ans = ln + rn; if(fa == -1) return lc[ls] == mid - x + 1 ? lc[ls] + rn : lc[ls]; else return rc[rs] == y - mid ? rc[rs] + ln : rc[rs]; } return fa == -1 ? lc[ls] : rc[rs]; } } void refresh(int cur, int x, int y, int s, int t, int v) { int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x >= s && y <= t) { add[cur] += v, lx[cur] += v, rx[cur] += v; return ; } pushdown(cur); if(mid >= s) refresh(ls, x, mid, s, t, v); if(mid + 1 <= t) refresh(rs, mid + 1, y, s, t, v); update(cur, x, y); } void solve() { int i, j, k, x, y, z, ans; char b[5]; for(i = 0; i < Q; i ++) { scanf("%s", b); if(b[0] == 'q') { scanf("%d%d", &x, &y); ans = 0; query(1, 1, N, x, y, -1, ans); printf("%d\n", ans); } else { scanf("%d%d%d", &x, &y, &z); refresh(1, 1, N, x, y, z); } } } int main() { int t, tt; scanf("%d", &t); for(tt = 0; tt < t; tt ++) { init(); printf("Case #%d:\n", tt + 1); solve(); } return 0; }