没搞懂为什么这么慢啊,是访问不连续吗?
#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;
}