题解 [SNOI2022] 军队
什么都不能维护嘛,看着挺分块的
边角是容易处理的
整块的标记也好打
但标记怎么下放呢?
发现只关心每种颜色在经过一个序列的操作后会变成什么颜色
所以对每个块维护操作序列,倒序处理即可
需要调整块长来卡空间
时间复杂度 \(O(n^{1.55})\),空间复杂度 \(O(n^{1.45})\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 250010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, q, c;
ll val[N];
int col[N];
namespace force{
void solve() {
for (int i=1,op,l,r,x,y; i<=q; ++i) {
op=read();
if (op==1) {
l=read(); r=read(); x=read(); y=read();
for (int j=l; j<=r; ++j) if (col[j]==x) col[j]=y;
}
else if (op==2) {
l=read(); r=read(); x=read(); y=read();
for (int j=l; j<=r; ++j) if (col[j]==x) val[j]+=y;
}
else if (op==3) {
l=read(); r=read();
ll ans=0;
for (int j=l; j<=r; ++j) ans+=val[j];
printf("%lld\n", ans);
}
}
}
}
namespace task1{
const int blc=275;
bool typ[blc][N];
short cnt[blc][N];
ll sum[blc], add[N];
struct tags{int fir, sec;}tag[blc][N];
int bel[N], ls[N], rs[N], tr[N], top[blc], sqr;
void spread(int id) {
for (int i=ls[id]; i<=rs[id]; ++i) tr[col[i]]=col[i], add[col[i]]=0;
for (int i=1; i<=top[id]; ++i) {
tr[tag[id][i].fir]=tag[id][i].fir, add[tag[id][i].fir]=0;
if (typ[id][i]) tr[tag[id][i].sec]=tag[id][i].sec, add[tag[id][i].sec]=0;
}
for (int x,y; top[id]; --top[id]) {
x=tag[id][top[id]].fir, y=tag[id][top[id]].sec;
if (typ[id][top[id]]) tr[x]=tr[y], add[x]=add[y];
else add[x]+=y;
}
for (int i=ls[id]; i<=rs[id]; ++i) val[i]+=add[col[i]], col[i]=tr[col[i]];
}
void solve() {
// cout<<double(sizeof(tag)+sizeof(cnt)+sizeof(typ))/1000/1000<<endl;
sqr=pow(n, 0.55);
for (int i=1; i<=n; ++i) bel[i]=(i-1)/sqr+1;
for (int i=1; i<=n; ++i) rs[bel[i]]=i;
for (int i=n; i; --i) ls[bel[i]]=i;
for (int i=1; i<=n; ++i) sum[bel[i]]+=val[i], ++cnt[bel[i]][col[i]];
for (int i=1,op,l,r,x,y; i<=q; ++i) {
op=read();
if (op==1) {
l=read(); r=read(); x=read(); y=read();
int sid=bel[l], eid=bel[r];
if (sid==eid) {
spread(sid);
for (int j=l; j<=r; ++j) if (col[j]==x)
--cnt[sid][x], ++cnt[sid][col[j]=y];
continue;
}
spread(sid), spread(eid);
for (int j=l; bel[j]==sid; ++j) if (col[j]==x)
--cnt[sid][x], ++cnt[sid][col[j]=y];
for (int j=sid+1; j<eid; ++j)
cnt[j][y]+=cnt[j][x], cnt[j][x]=0, tag[j][++top[j]]={x, y}, typ[j][top[j]]=1;
for (int j=r; bel[j]==eid; --j) if (col[j]==x)
--cnt[eid][x], ++cnt[eid][col[j]=y];
}
else if (op==2) {
l=read(); r=read(); x=read(); y=read();
int sid=bel[l], eid=bel[r];
if (sid==eid) {
spread(sid);
for (int j=l; j<=r; ++j) if (col[j]==x)
val[j]+=y, sum[sid]+=y;
continue;
}
spread(sid), spread(eid);
for (int j=l; bel[j]==sid; ++j) if (col[j]==x)
val[j]+=y, sum[sid]+=y;
for (int j=sid+1; j<eid; ++j)
sum[j]+=1ll*cnt[j][x]*y, tag[j][++top[j]]={x, y}, typ[j][top[j]]=0;
for (int j=r; bel[j]==eid; --j) if (col[j]==x)
val[j]+=y, sum[eid]+=y;
}
else if (op==3) {
l=read(); r=read();
int sid=bel[l], eid=bel[r]; ll ans=0;
if (sid==eid) {
spread(sid);
for (int j=l; j<=r; ++j) ans+=val[j];
printf("%lld\n", ans);
continue;
}
spread(sid), spread(eid);
for (int j=l; bel[j]==sid; ++j) ans+=val[j];
for (int j=sid+1; j<eid; ++j) ans+=sum[j];
for (int j=r; bel[j]==eid; --j) ans+=val[j];
printf("%lld\n", ans);
}
}
// for (int i=1; i<=bel[n]; ++i) spread(i);
// cout<<"val: "; for (int i=1; i<=n; ++i) cout<<val[i]<<' '; cout<<endl;
// cout<<"col: "; for (int i=1; i<=n; ++i) cout<<col[i]<<' '; cout<<endl;
}
}
signed main()
{
// freopen("military.in", "r", stdin);
// freopen("military.out", "w", stdout);
n=read(); q=read(); c=read();
for (int i=1; i<=n; ++i) val[i]=read();
for (int i=1; i<=n; ++i) col[i]=read();
// force::solve();
task1::solve();
return 0;
}