help! TLE 65
查看原帖
help! TLE 65
511676
naoliaok_lovely楼主2023/6/29 20:21

没搞懂为什么这么慢啊,是访问不连续吗?

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N = 250010, M = 2 * N, K = 850;
int n, m, c, block = 300, block_id[N], blockl[K], blockr[K];
int b[M];
LL a[M];
vector<int> e[M], root[K];
int color[K][N], cnt[M];
LL ans[K];
int rub[M], rub_tt;

char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char gc()
{
	if(p1 == p2)
		p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin);
	return p1 == p2 ? EOF : *p1++;
}
inline int read()
{
	int f = 1, w = 0;
	char ch = gc();
	while(ch < '0' || '9' < ch)
	{
		if(ch == '-') f = -1;
		ch = gc();
	}
	while('0' <= ch && ch <= '9')
	{
		w = (w << 1) + (w << 3) + (ch ^ 48);
		ch = gc();
	}
	return f * w;
}
char obuf[1 << 21], *p3 = obuf;
inline void pc(char c)
{
	p3 - obuf <= 1 << 20 ? *p3++ = c : (fwrite(obuf, p3 - obuf, 1, stdout), p3 = obuf, *p3++ = c);
}
inline void write(LL x)
{
	if(x < 0) pc('-'), x = -x;
	if(x > 9) write(x / 10);
	pc(x % 10 ^ 48);
}

inline int min(int a, int b)
{
	return a < b ? a : b;
}
inline int max(int a, int b)
{
	return a > b ? a : b;
}

inline void build(int x)
{
	register int l = blockl[x], r = blockr[x];
	for(register int i = l; i <= r; ++i)
	{
		cnt[i] = 1;
		if(!color[x][b[i]]) color[x][b[i]] = i, root[x].push_back(i);
		else if(color[x][b[i]] <= n)
		{
			int t = rub[rub_tt--];
			b[t] = b[i], e[t].push_back(color[x][b[i]]), e[t].push_back(i);
			color[x][b[i]] = t, cnt[t] = 2, root[x].push_back(t);
		}
		else e[color[x][b[i]]].push_back(i), ++cnt[color[x][b[i]]];
	}
}

int q[N], tt;
inline void reset(int x)
{
	register int l = blockl[x], r = blockr[x];
	for(int i : root[x])
	{
		if(!color[x][b[i]]) continue;
		q[tt = 1] = color[x][b[i]];
		while(tt)
		{
			int t = q[tt--];
			for(int j : e[t]) a[j] += a[t], q[++tt] = j;
			e[t].clear();
			if(t <= n) b[t] = b[i];
			else rub[++rub_tt] = t, a[t] = 0;
		}
		color[x][b[i]] = 0;
	}
	root[x].clear();
}

inline void modify1(int l, int r, int x, int y)
{
	if(block_id[l] == block_id[r])
	{
		reset(block_id[l]);
		for(register int i = l; i <= r; ++i)
			if(b[i] == x) b[i] = y;
		build(block_id[l]);
		return;
	}
	
	reset(block_id[l]), reset(block_id[r]);
	register int i = l, j = r;
	while(block_id[i] == block_id[l])
	{
		if(b[i] == x) b[i] = y;
		++i;
	}
	while(block_id[j] == block_id[r])
	{
		if(b[j] == x) b[j] = y;
		--j;
	}
	build(block_id[l]), build(block_id[r]);
	
	for(register int i = block_id[l] + 1; i < block_id[r]; ++i)
	{
		if(!color[i][x]) continue;
		if(!color[i][y]) color[i][y] = color[i][x], color[i][x] = 0, b[color[i][y]] = y;
		else
		{
			int t = rub[rub_tt--];
			b[t] = y, e[t].push_back(color[i][x]), e[t].push_back(color[i][y]);
			cnt[t] = cnt[color[i][x]] + cnt[color[i][y]], color[i][x] = 0, color[i][y] = t, root[i].push_back(t);
		}
	}
}

inline void modify2(int l, int r, int x, int y)
{
	if(block_id[l] == block_id[r])
	{
		reset(block_id[l]);
		for(register int i = l; i <= r; ++i)
			if(b[i] == x) a[i] += y, ans[block_id[l]] += y;
		build(block_id[l]);
		return;
	}
	
	reset(block_id[l]), reset(block_id[r]);
	register int i = l, j = r;
	while(block_id[i] == block_id[l])
	{
		if(b[i] == x) a[i] += y, ans[block_id[l]] += y;
		++i;
	}
	while(block_id[j] == block_id[r])
	{
		if(b[j] == x) a[j] += y, ans[block_id[r]] += y;
		--j;
	}
	build(block_id[l]), build(block_id[r]);
	
	for(register int i = block_id[l] + 1; i < block_id[r]; ++i)
	{
		if(!color[i][x]) continue;
		a[color[i][x]] += y, ans[i] += 1ll * cnt[color[i][x]] * y;
	}
}

inline LL getans(int l, int r)
{
	if(block_id[l] == block_id[r])
	{
		reset(block_id[l]);
		LL res = 0;
		for(int i = l; i <= r; i++) res += a[i];
		build(block_id[l]);
		return res;
	}
	
	reset(block_id[l]), reset(block_id[r]);
	register int i = l, j = r;
	LL res = 0;
	while(block_id[i] == block_id[l]) res += a[i++];
	while(block_id[j] == block_id[r]) res += a[j--];
	build(block_id[l]), build(block_id[r]);
	
	for(register int i = block_id[l] + 1; i < block_id[r]; ++i) res += ans[i];
	
	return res;
}

int main()
{
	n = read(), m = read(), c = read();
	for(register int i = 1; i <= n; ++i) a[i] = read();
	for(register int i = 1; i <= n; ++i) b[i] = read();
	
	for(register int i = n + 1; i < M; ++i) rub[++rub_tt] = i;
	for(register int i = 1; i <= n; ++i) block_id[i] = i / block;
	for(register int i = 0; i <= n / block; ++i)
		blockl[i] = max(i * block, 1), blockr[i] = min(i * block + block - 1, n);
	for(register int i = 0; i <= n / block; ++i) build(i);
	for(register int i = 1; i <= n; ++i) ans[block_id[i]] += a[i];
	
	while(m--)
	{
		int op, l, r, x, y;
		op = read(), l = read(), r = read();
		if(op == 1)
		{
			x = read(), y = read();
			modify1(l, r, x, y);
		}
		else if(op == 2)
		{
			x = read(), y = read();
			modify2(l, r, x, y);
		}
		else
			write(getans(l, r)), pc('\n');
	}
	
	fwrite(obuf, p3 - obuf, 1, stdout);
	return 0;
}
2023/6/29 20:21
加载中...