题解 [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;
}
posted @ 2022-07-02 21:27  Administrator-09  阅读(3)  评论(0编辑  收藏  举报