社区讨论

求条玄关

P6242【模板】线段树 3(区间最值操作、区间历史最值)参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@miwuxwtp
此快照首次捕获于
2025/12/08 15:56
2 个月前
此快照最后确认于
2025/12/11 15:10
2 个月前
查看原帖
只 AC 3,4,9,矩阵写法
CPP
#include <bits/stdc++.h>

#define int long long
#define ls(x) ((x) << 1)
#define rs(x) ((x) << 1 | 1)

using namespace std;

const int N = 5e5 + 5;

int n, m, a[N];

struct mat {
	int a[2][2];
	mat() {
	    memset(a, -0x3f, sizeof(a));	
	}
	mat operator * (const mat b) const {
		mat c;
		for (int i = 0; i < 2; ++ i )
		    for (int j = 0; j < 2; ++ j )
		        for (int k = 0; k < 2; ++ k )
		            c.a[i][j] = max(c.a[i][j], a[i][k] + b.a[k][j]);
		
		return c;
	}
	mat operator + (const mat b) const {
		mat c;
		for (int i = 0; i < 2; ++ i )
		    for (int j = 0; j < 2; ++ j )
		        c.a[i][j] = max(a[i][j], b.a[i][j]);
		        
		return c;
	} 
};

struct node {
	int l, r, m1, m2, cnt, sum, add1, add2;
	mat a, add, tag;
	int f1, f2;
};

node t[4 * N];

void push_up (int p) {
	t[p].sum = t[ls(p)].sum + t[rs(p)].sum;
	t[p].m1 = max(t[ls(p)].m1, t[rs(p)].m1);
	t[p].m2 = max(t[ls(p)].m2, t[rs(p)].m2);
	if (t[p].m1 != t[ls(p)].m1) t[p].m2 = max(t[p].m2, t[ls(p)].m1);
	if (t[p].m1 != t[rs(p)].m1) t[p].m2 = max(t[p].m2, t[rs(p)].m1);
	t[p].cnt = 0;
	if (t[p].m1 == t[ls(p)].m1) t[p].cnt += t[ls(p)].cnt;
	if (t[p].m1 == t[rs(p)].m1) t[p].cnt += t[rs(p)].cnt;
	t[p].a = t[ls(p)].a + t[rs(p)].a;
	return;
}

void build (int l, int r, int p) {
	t[p].l = l, t[p].r = r;
	if (l == r) {
		t[p].sum = t[p].m1 = a[l];
		t[p].m2 = -1e18;
		t[p].cnt = 1;
		t[p].a.a[0][0] = t[p].a.a[0][1] = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build (l, mid, ls(p));
	build (mid + 1, r, rs(p));
	push_up(p);
	return; 
}

void lazy_tag1 (int p, int d) {
	t[p].sum += (t[p].r - t[p].l + 1) * d;
	t[p].m1  += d;
	t[p].m2  += d;
	t[p].add1 += d;
	return;
} 

void lazy_tag2 (int p, int d) {
	t[p].sum += t[p].cnt * d;
	t[p].m1  += d;
	t[p].add2 += d;
	return;
}

void lazy_tag3 (int p, mat now) {
	if (t[p].f1) t[p].add = t[p].add * now;
	else t[p].add = now, t[p].f1 = true;
	return;
}

void lazy_tag4 (int p, mat now) {
	if (t[p].f2) t[p].tag = t[p].tag * now;
	else t[p].tag = now, t[p].f2 = true;
	return;
}

void push_down (int p) {
    
    int mx = max(t[ls(p)].m1, t[rs(p)].m1);
    if (t[ls(p)].m1 == mx) {
		if (t[p].f1) {
			t[ls(p)].a = t[ls(p)].a * t[p].add;
			lazy_tag3 (ls(p), t[p].add);
			if (t[p].f2) {
				lazy_tag4 (ls(p), t[p].tag);
			}
		} else if (t[p].f2) {
			lazy_tag4 (ls(p), t[p].tag);
		}
	} else {
		if (t[p].f2) {
			t[ls(p)].a = t[ls(p)].a * t[p].tag; 
			lazy_tag4 (ls(p), t[p].tag);
		}
	}
	if (t[rs(p)].m1 == mx) {
		if (t[p].f1) {
			t[rs(p)].a = t[rs(p)].a * t[p].add;
			lazy_tag3 (rs(p), t[p].add);
			if (t[p].f2) {
				lazy_tag4 (rs(p), t[p].tag);
			}
		} else if (t[p].f2) {
			lazy_tag4 (rs(p), t[p].tag);
		}
	} else {
		if (t[p].f2) {
			t[rs(p)].a = t[rs(p)].a * t[p].tag;
			lazy_tag4 (rs(p), t[p].tag);
		}
	}
	if (t[ls(p)].m1 == mx) lazy_tag2 (ls(p), t[p].add2);
	if (t[rs(p)].m1 == mx) lazy_tag2 (rs(p), t[p].add2);
	t[p].f1 = t[p].f2 = false;
	lazy_tag1 (ls(p), t[p].add1);
	lazy_tag1 (rs(p), t[p].add1);
	t[p].add1 = t[p].add2 = 0; 
	return;
}

void update (int l, int r, int p, int d) {
	if (l <= t[p].l && t[p].r <= r) {
	    mat now;
		now.a[0][0] = now.a[0][1] = d;
		now.a[1][0] = -1e18, now.a[1][1] = 0;
		t[p].a = t[p].a * now;
		lazy_tag3 (p, now); 
		lazy_tag4 (p, now);
		lazy_tag1 (p, d);
		return;
	}
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) update (l, r, ls(p), d);
	if (r >  mid) update (l, r, rs(p), d);
	push_up(p);
	return; 
}

void modify (int l, int r, int p, int d) {
	if (t[p].m1 <= d) return;
	if (l <= t[p].l && t[p].r <= r && t[p].m2 < d) {
	    mat now;
		now.a[0][0] = now.a[0][1] = d - t[p].m1;
		now.a[1][0] = -1e18, now.a[1][1] = 0;
		t[p].a = t[p].a * now;
		lazy_tag3 (p, now); 
		lazy_tag2 (p, d - t[p].m1);
		return;
	}
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) modify (l, r, ls(p), d);
	if (r >  mid) modify (l, r, rs(p), d);
	push_up(p);
	return; 
}

int query1 (int l, int r, int p) {
	if (l <= t[p].l && t[p].r <= r) return t[p].sum;
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid && r > mid) return query1 (l, r, ls(p)) + query1 (l, r, rs(p));
	if (l <= mid) return query1 (l, r, ls(p));
	return query1 (l, r, rs(p));
}

int query2 (int l, int r, int p) {
	if (l <= t[p].l && t[p].r <= r) return t[p].m1;
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid && r > mid) return max(query2 (l, r, ls(p)), query2 (l, r, rs(p)));
	if (l <= mid) return query2 (l, r, ls(p));
	return query2 (l, r, rs(p));
}

int query3 (int l, int r, int p) {
	if (l <= t[p].l && t[p].r <= r) return t[p].a.a[0][1];
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid && r > mid) return max(query3 (l, r, ls(p)), query3 (l, r, rs(p)));
	if (l <= mid) return query3 (l, r, ls(p));
	return query3 (l, r, rs(p));
}

signed main() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; ++ i ) scanf("%lld", a + i);
	build (1, n, 1);
	while (m -- ) {
		int o, l, r, k, v;
		scanf("%lld%lld%lld", &o, &l, &r);
		if (o == 1) {
			scanf("%lld", &k);
			update (l, r, 1, k);
		} else if (o == 2) {
			scanf("%lld", &v);
			modify (l, r, 1, v);
		} else if (o == 3) {
			printf("%lld\n", query1 (l, r, 1));
 		} else if (o == 4) {
 			printf("%lld\n", query2 (l, r, 1));
		} else {
			printf("%lld\n", query3 (l, r, 1));
		} 
	}
	return 0; 
}

回复

2 条回复,欢迎继续交流。

正在加载回复...