20pts吉司机线段树秋条玄关
查看原帖
20pts吉司机线段树秋条玄关
762199
fulichang楼主2024/11/4 08:19
//from.luogu P10639 by.flic 24-10-30
//https://www.luogu.com.cn/problem/P10639
#include <bits/stdc++.h>
#define int long long

using namespace std;

const int N = 5e5 + 10, inf = 1e18;

struct node {
	int sum, valmax, cntmax, secmax, valmin, cntmin, secmin;
	friend node operator + (node a, node b) {
		node c;
		c.sum = a.sum + b.sum;
		c.valmax = max(a.valmax, b.valmax);
		if (a.valmax == b.valmax)
			c.cntmax = a.cntmax + b.cntmax,  c.secmax = max(a.secmax, b.secmax);
		else if (a.valmax > b.valmax)
			c.cntmax = a.cntmax, c.secmax = max(a.secmax, b.valmax);
		else
			c.cntmax = b.cntmax, c.secmax = max(b.secmax, a.valmax);
		c.valmin = min(a.valmin, b.valmin);
		if (a.valmin == b.valmin)
			c.cntmin = a.cntmin + b.cntmin, c.secmin = min(a.secmin, b.secmin);
		else if (a.valmin < b.valmin)
			c.cntmin = a.cntmin, c.secmin = min(a.secmin, b.valmin);
		else
			c.cntmin = b.cntmin, c.secmin = min(b.secmin, a.valmin);
		return c;
	}
};

int n, m;
int a[N], MaxAdd[N << 2], MaxOtherAdd[N << 2], MinAdd[N << 2], MinMax[N << 2], MinOtherAdd[N << 2];
node tree[N << 2];

void pushup (int rt) {
	tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}

void build (int l, int r, int rt) {
	if (l == r) {
		tree[rt] = {a[l], a[l], 1, -inf, a[l], 1, inf};
		return ;
	}
	int mid = l + r >> 1;
	build(l, mid, rt << 1);
	build(mid + 1, r, rt << 1 | 1);
	pushup(rt);
}

void lazy (int len, int rt, int maxadd, int maxotheradd, int minadd, int minmax, int minotheradd) {
	tree[rt].sum += maxadd * tree[rt].cntmax + maxotheradd * (len - tree[rt].cntmax) + minmax * tree[rt].cntmin;
	if (tree[rt].valmax == tree[rt].valmin) {
        if (maxadd) 
            tree[rt].valmax = tree[rt].valmin = tree[rt].valmax + maxadd;
        else
            tree[rt].valmax = tree[rt].valmin = tree[rt].valmax + minadd;
        tree[rt].valmax = tree[rt].valmin = tree[rt].valmax + minmax;
	}
	else if (tree[rt].valmax == tree[rt].secmin) {
        tree[rt].secmin = tree[rt].valmax = tree[rt].valmax + maxadd;
        tree[rt].secmax = tree[rt].valmin = tree[rt].valmin + minadd + minmax;
	}
	else {
    	tree[rt].valmax += maxadd;
	    tree[rt].secmax += tree[rt].secmax == -inf ? 0 : maxotheradd;
        tree[rt].valmin += minadd + minmax;
        tree[rt].secmin += tree[rt].secmin == inf ? 0 : minotheradd;
    }
	MaxAdd[rt] += maxadd;
	MaxOtherAdd[rt] += maxotheradd;
    MinAdd[rt] += minadd;
    MinMax[rt] += minmax;
    MinOtherAdd[rt] += minotheradd;
}

void pushdown (int l, int r, int rt) {
	int mid = l + r >> 1, tmpmax = max(tree[rt << 1].valmax, tree[rt << 1 | 1].valmax), tmpmin = min(tree[rt << 1].valmin, tree[rt << 1 | 1].valmin);
	if (tree[rt << 1].valmax == tmpmax)
		lazy(mid - l + 1, rt << 1, MaxAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
	else
		lazy(mid - l + 1, rt << 1, MaxOtherAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
	if (tree[rt << 1 | 1].valmax == tmpmax)
		lazy(r - mid, rt << 1 | 1, MaxAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
	else
		lazy(r - mid, rt << 1 | 1, MaxOtherAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
	if (tree[rt << 1].valmin == tmpmin)
		lazy(mid - l + 1, rt << 1, 0, 0, MinAdd[rt], MinMax[rt], MinOtherAdd[rt]);
	else
		lazy(mid - l + 1, rt << 1, 0, 0, MinOtherAdd[rt], 0, MinOtherAdd[rt]);
	if (tree[rt << 1 | 1].valmin == tmpmin)
		lazy(r - mid, rt << 1 | 1, 0, 0, MinAdd[rt], MinMax[rt], MinOtherAdd[rt]);
	else
		lazy(r - mid, rt << 1 | 1, 0, 0, MinOtherAdd[rt], 0, MinOtherAdd[rt]);
	MaxAdd[rt] = MaxOtherAdd[rt] = MinAdd[rt] = MinMax[rt] = MinOtherAdd[rt] = 0;
}

void add (int l, int r, int rt, int L, int R, int c) {
	if (L <= l && r <= R) {
		lazy(r - l + 1, rt, c, c, c, 0, c);
		return ;
	}
	pushdown(l, r, rt);
	int mid = l + r >> 1;
	if (L <= mid)
		add(l, mid, rt << 1, L, R, c);
	if (R > mid)
		add(mid + 1, r, rt << 1 | 1, L, R, c);
	pushup(rt);
}

void setmax (int l, int r, int rt, int L, int R, int c) {
	if (tree[rt].valmin >= c)
		return ;
	if (L <= l && r <= R && tree[rt].secmin > c) {
        lazy(r - l + 1, rt, 0, 0, 0, c - tree[rt].valmin, 0);
		return ;
	}
	pushdown(l, r, rt);
	int mid = l + r >> 1;
	if (L <= mid)
		setmax(l, mid, rt << 1, L, R, c);
	if (R > mid)
		setmax(mid + 1, r, rt << 1 | 1, L, R, c);
	pushup(rt);
}

void setmin (int l, int r, int rt, int L, int R, int c) {
	if (tree[rt].valmax <= c)
		return ;
	if (L <= l && r <= R && tree[rt].secmax < c) {
		lazy(r - l + 1, rt, c - tree[rt].valmax, 0, 0, 0, 0);
		return ;
	}
	pushdown(l, r, rt);
	int mid = l + r >> 1;
	if (L <= mid)
		setmin(l, mid, rt << 1, L, R, c);
	if (R > mid)
		setmin(mid + 1, r, rt << 1 | 1, L, R, c);
	pushup(rt);
}

node query (int l, int r, int rt, int L, int R) {
	if (L <= l && r <= R)
		return tree[rt];
	pushdown(l, r, rt);
	int mid = l + r >> 1;
	if (R <= mid)
		return query(l, mid, rt << 1, L, R);
	if (L > mid)
		return query(mid + 1, r, rt << 1 | 1, L, R);
	return query(l, mid, rt << 1, L, R) + query(mid + 1, r, rt << 1 | 1, L, R);
}

signed main (void) {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	build(1, n, 1);
	cin >> m;
	while (m--) {
		int op, x, y, z;
		cin >> op >> x >> y;
		if (op == 1)
			cin >> z, add(1, n, 1, x, y, z);
		else if (op == 2)
			cin >> z, setmax(1, n, 1, x, y, z);
		else if (op == 3)
			cin >> z, setmin(1, n, 1, x, y, z);
		else {
			node tmp = query(1, n, 1, x, y);
			if (op == 4)
				cout << tmp.sum << '\n';
			else if (op == 5)
				cout << tmp.valmax << '\n';
			else
				cout << tmp.valmin << '\n';
		}
	}
	return 0;
}
2024/11/4 08:19
加载中...