40pts求调,only ac on#1,5,9,10
查看原帖
40pts求调,only ac on#1,5,9,10
1132682
GUAIKATTO楼主2024/10/18 23:31

不明白为啥9,10能过中间的过不了,debug发现问题多出在操作4且结果为大负数的情况

#include <iostream>
#include <climits>
using namespace std;

#define maxn 1000001
long long LOWEST = LONG_MIN;
int arr[maxn];
long long sum[maxn << 2];
long long maxnum[maxn << 2];
long long semaxn[maxn << 2];
int maxcnt[maxn << 2];

long long maxadd[maxn << 2];
long long otheradd[maxn << 2];

long long maxHistory[maxn << 2];
long long maxaddTop[maxn << 2];// 最大值达到过的最大提升幅度(懒更新信息)
long long otheraddTop[maxn << 2];// 除最大值以外的其他数字,达到过的最大提升幅度(懒更新信息)

int ope[maxn][4];


// maxAddv   : 最大值增加多少
// otherAddv : 其他数增加多少
// maxUpv    : 最大值达到过的最大提升幅度
// otherUpv  : 其他数达到过的最大提升幅度

void lazy(int i, int size, int maxAddv, int otherAddv, int maxUpv, int otherUpv)
{
	maxHistory[i] = max(maxHistory[i], maxnum[i] + maxUpv);
	maxaddTop[i] = max(maxaddTop[i], maxadd[i] + maxUpv);
	otheraddTop[i] = max(otheraddTop[i], otheradd[i] + otherUpv);

	sum[i] += maxAddv * maxcnt[i] + otherAddv * (size - maxcnt[i]);
	maxnum[i] += maxAddv;
	semaxn[i] += semaxn[i] == LOWEST ? 0 : otherAddv;

	maxadd[i] += maxAddv;
	otheradd[i] += otherAddv;
}

void up(int i)
{
	int l = i << 1;
	int r = i << 1 | 1;
	sum[i] = sum[l] + sum[r];
	if (maxnum[l] > maxnum[r])
	{
		maxnum[i] = maxnum[l];
		semaxn[i] = max(maxnum[r], semaxn[l]);
		maxcnt[i] = maxcnt[l];
	}
	else if (maxnum[l] < maxnum[r])
	{
		maxnum[i] = maxnum[r];
		semaxn[i] = max(maxnum[l], semaxn[r]);
		maxcnt[i] = maxcnt[r];
	}
	else
	{
		maxnum[i] = maxnum[l];
		semaxn[i] = max(semaxn[l], semaxn[r]);
		maxcnt[i] = maxcnt[l] + maxcnt[r];
	}
	maxHistory[i] = max(maxHistory[l], maxHistory[r]);
}

void down(int i, int ln, int rn)
{
	int l = i << 1;
	int r = i << 1 | 1;
	long long tmp = max(maxnum[l], maxnum[r]);

	if (maxnum[l] == tmp)
	{
		lazy(l, ln, maxadd[i], otheradd[i], maxaddTop[i], otheraddTop[i]);
	}
	else
	{
		lazy(l, ln, otheradd[i], otheradd[i], otheraddTop[i], otheraddTop[i]);
	}

	if (maxnum[r] == tmp)
	{
		lazy(r, rn, maxadd[i], otheradd[i], maxaddTop[i], otheraddTop[i]);
	}
	else
	{
		lazy(r, rn, otheradd[i], otheradd[i], otheraddTop[i], otheraddTop[i]);
	}
	maxadd[i] = otheradd[i] = maxaddTop[i] = otheraddTop[i] = 0;
}

void setMin(int jobl, int jobr, int jobv, int l, int r, int i)
{
	if (jobv >= maxnum[i])return;
	if (l >= jobl && r <= jobr && semaxn[i] < jobv)
	{
		lazy(i, r - l + 1, jobv - maxnum[i], 0, jobv - maxnum[i], 0);
	}
	else
	{
		int mid = (l + r) / 2;
		down(i, mid - l + 1, r - mid);
		if (jobl <= mid)//左结点在目标范围中
		{
			setMin(jobl, jobr, jobv, l, mid, i << 1);
		}
		if (jobr > mid)//右节点在目标范围中
		{
			setMin(jobl, jobr, jobv, mid + 1, r, i << 1 | 1);
		}
		up(i);
	}
}

void addnum(int jobl, int jobr, long long jobv, int l, int r, int i)
{
	if (l >= jobl && r <= jobr)//如果目标范围完全覆盖当前范围
	{
		lazy(i, r - l + 1, jobv, jobv, jobv, jobv);
	}
	else
	{
		int mid = (l + r) >> 1;
		down(i, mid - l + 1, r - mid);//懒信息向下传递
		if (jobl <= mid)//左结点在目标范围中
		{
			addnum(jobl, jobr, jobv, l, mid, i << 1);
		}
		if (jobr > mid)//右节点在目标范围中
		{
			addnum(jobl, jobr, jobv, mid + 1, r, i << 1 | 1);
		}
		up(i);
	}
}

long long querySum(int jobl, int jobr, int l, int r, int i)
{
	if (l >= jobl && r <= jobr)//如果目标范围完全覆盖当前范围
	{
		return sum[i];
	}
	int mid = (l + r) >> 1;
	down(i, mid - l + 1, r - mid);//懒信息向下传递
	long long ans = 0;
	if (jobl <= mid)//左节点在目标范围中
	{
		ans += querySum(jobl, jobr, l, mid, i << 1);
	}
	if (jobr > mid)//右节点在目标范围中
	{
		ans += querySum(jobl, jobr, mid + 1, r, i << 1 | 1);
	}
	return ans;
}

long long queryMax(int jobl, int jobr, int l, int r, int i)
{
	if (l >= jobl && r <= jobr)//如果目标范围完全覆盖当前范围
	{
		return maxnum[i];
	}
	int mid = (l + r) >> 1;
	down(i, mid - l + 1, r - mid);//懒信息向下传递
	if (jobr <= mid)
	{
		return queryMax(jobl, jobr, l, mid, i << 1);
	}
	if (jobl > mid)
	{
		return queryMax(jobl, jobr, mid + 1, r, i << 1 | 1);
	}
	return max(queryMax(jobl, jobr, l, mid, i << 1), queryMax(jobl, jobr, mid + 1, r, i << 1 | 1));
}

long long queryHistoryMax(int jobl, int jobr, int l, int r, int i)
{
	if (l >= jobl && r <= jobr)//如果目标范围完全覆盖当前范围
	{
		return maxHistory[i];
	}
	int mid = (l + r) >> 1;
	down(i, mid - l + 1, r - mid);//懒信息向下传递
	if (jobr <= mid)
	{
		return queryHistoryMax(jobl, jobr, l, mid, i << 1);
	}
	if (jobl > mid)
	{
		return queryHistoryMax(jobl, jobr, mid + 1, r, i << 1 | 1);
	}
	return max(queryHistoryMax(jobl, jobr, l, mid, i << 1), queryHistoryMax(jobl, jobr, mid + 1, r, i << 1 | 1));
}

void build(int l, int r, int i)
{
	if (l == r)
	{
		sum[i] = arr[l];
		maxnum[i] = arr[l];
		maxHistory[i] = arr[l];
		semaxn[i] = LOWEST;
		maxcnt[i] = 1;
	}
	else
	{
		int mid = (l + r) >> 1;
		build(l, mid, i << 1);
		build(mid + 1, r, i << 1 | 1);
		up(i);
	}
	maxadd[i] = otheradd[i] = maxaddTop[i] = otheraddTop[i] = 0;
}

int main()
{
	int n, m, temp;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)cin >> arr[i];
	for (int i = 0; i < m; i++)
	{
		cin >> temp;
		ope[i][0] = temp;
		if (temp == 1 || temp == 2)
		{
			for (int j = 1; j < 4; j++)
			{
				cin >> ope[i][j];
			}
		}
		else if (temp == 3 || temp == 4 || temp == 5)
		{
			for (int j = 1; j < 3; j++)
			{
				cin >> ope[i][j];
			}
		}
		else
		{
			cout << "ERROR";
			return 0;
		}
	}
	build(1, n, 1);
	for (int i = 0; i < m; i++)
	{
		temp = ope[i][0];
		if (temp == 1)
		{
			addnum(ope[i][1], ope[i][2], ope[i][3], 1, n, 1);
		}
		else if (temp == 2)
		{
			setMin(ope[i][1], ope[i][2], ope[i][3], 1, n, 1);
		}
		else if (temp == 3)
		{
			cout << querySum(ope[i][1], ope[i][2], 1, n, 1) << endl;
		}
		else if (temp == 4)
		{
			cout << queryMax(ope[i][1], ope[i][2], 1, n, 1) << endl;
		}
		else if (temp == 5)
		{
			cout << queryHistoryMax(ope[i][1], ope[i][2], 1, n, 1) << endl;
		}
		else
		{
			cout << "ERROR";
			return 0;
		}
	}
}
2024/10/18 23:31
加载中...