第二分块MLE求调
查看原帖
第二分块MLE求调
408071
TankYu楼主2023/2/4 20:50
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

int n, m;
int a[1000010];//原数组
int op[500010];//操作类型(以下三个如题意)
int l[500010];
int r[500010];
int x[500010];
int ans[500010];//对于操作2的答案
int id[200010];//将数映射的值
int fa[200010];//并查集祖先关系
int size[200010];//并查集大小
int value[200010];//原值

int L, R, Size; //单块左界,右界,块大小

int Find(int x)
{
	if (x == fa[x])
	{
		return fa[x];
	}
	fa[x] = Find(fa[x]);
	return fa[x];
}

void Merge(int x, int y)
{
	if (id[y])
	{
		fa[id[x]] = id[y];
	}
	else
	{
		id[y] = id[x];
		value[id[y]] = y;
	}
	size[y] += size[x];
	id[x] = 0;
	size[x] = 0;
	return;
}

int tag;//整体减法tag

void Delete()
{
	for (int i = L; i <= R; i++)
	{
		a[i] = value[Find(i)];
		id[a[i]] = 0;
		size[a[i]] = 0;
		a[i] -= tag;
	}
	for (int i = L; i <= R; i++)
	{
		fa[i] = 0;
	}
	tag = 0;
	return;
}

int maxx;

void Remake()
{
	maxx = 0;
	for (int i = L; i <= R; i++)
	{
		if (!id[a[i]])
		{
			id[a[i]] = i;
			value[i] = a[i];
			fa[i] = i;
		}
		else
		{
			fa[i] = id[a[i]];
		}
		size[a[i]]++;
		maxx = max(maxx, a[i]);
	}
	return;
}

void Allupdate(int x)
{
	if (maxx - tag >= (x << 1))
	{
		for (int i = tag + 1; i <= tag + x; i++)
		{
			if (id[i])
			{
				Merge(i, i + x);
			}
		}
		tag += x;
	}
	else
	{
		for (int i = maxx; i > tag + x; i--)
		{
			if (id[i])
			{
				Merge(i, i - x);
			}
		}
		maxx = min(maxx, tag + x);
	}
	return;
}

void Partupdate(int ll, int rr, int x)
{
	if (ll > rr)
	{
		return;
	}
	Delete();
	for (int i = ll; i <= rr; i++)
	{
		if (a[i] > x)
		{
			a[i] -= x;
		}
	}
	Remake();
	return;
}

int Allquery(int x)
{
	if (x + tag > 200005)
	{
		return 0;
	}
	return size[x + tag];
}

int Partquery(int ll, int rr, int x)
{
	int ans = 0;
	for (int i = ll; i <= rr; i++)
	{
		if (value[Find(i)] - tag == x)
		{
			ans++;
		}
	}
	return ans;
}

int pos[1000010], bl[1100], br[1100];
//int zero_sum[1000010];

int main()
{
	scanf("%d%d", &n, &m);
	Size = 1145;
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
//		zero_sum[i] = zero_sum[i - 1] + (a[i] == 0);
	}
	for (int i = 1; i <= m; i++)
	{
		scanf("%d%d%d%d", &op[i], &l[i], &r[i], &x[i]);
	}
	for (register int i = 1; i <= n; i++)
		pos[i] = (i - 1) / Size + 1;
	for (register int i = 1; i <= pos[n]; i++)
	{
		bl[i] = (i - 1) * Size + 1;
		br[i] = min(i * Size, n);
	}
	for (int i = 1; i <= pos[n]; i++)
	{
		L = bl[i];
		R = br[i];
		Remake();
		for (int j = 1; j <= m; j++)
		{
			if (op[j] == 1)
			{
				if (l[j] <= L && r[j] >= R)
				{
					Allupdate(x[j]);
				}
				else
				{
					Partupdate(max(l[j], L), min(r[j], R), x[j]);
				}
			}
			else
			{
//				if (x[j] == 0)
//				{
//					ans[j] += zero_sum[min(R, r[j])] - zero_sum[max(L, l[j]) - 1];
//					continue;
//				}
				if (l[j] <= L && r[j] >= R)
				{
					ans[j] += Allquery(x[j]);
				}
				else
				{
					ans[j] += Partquery(max(l[j], L), min(r[j], R), x[j]);
				}
			}
		}
		Delete();
	}
	for (int i = 1; i <= m; i++)
	{
		if (op[i] == 2)
		{
			printf("%d\n", ans[i]);
		}
	}
	return 0;
}

要么全WA要么MLE+RE+TLE

2023/2/4 20:50
加载中...