其他分享
首页 > 其他分享> > CF794F

CF794F

作者:互联网

\(\tt Link\)

口胡十秒钟,调题两小时。

好的其实是个不难的 \(\tt {}^{\ast}2800\)(自我安慰。


考虑线段树。节点维护十种信息代表 \(0,\cdots,9\) 的权和。

权是啥?个位权是 \(1\),十位权是 \(10\),百位权是 \(100\),以此类推。
比如 \(2627\),\(2\) 的权是 \(1010\),\(6\) 的权是 \(100\),\(7\) 的权是 \(1\)。

于是一个节点代表的区间的和,就是 \(\sum\) 数字乘上其对应权。

我们发现有了这个权和,修改可以轻松转移。

考虑原来是 \(1243\)。
\(1\) 变 \(2\),这时把 \(1\) 的权加到 \(2\) 头上
\(2\) 再变 \(4\),这时再把 \(2\) 的权加到 \(4\) 头上。
完全没有问题,权和正确

考虑一个地方的修改。

我们对于线段树的节点维护 \(tag_i\) 代表数字 \(i\) 变成了什么。

打标记:\(\forall tag_i=x,tag_i\gets y\)。

当然同时要把 \(x\) 的权和累加到 \(y\) 头上。

考虑懒标记下传。直接枚举每个 \(x\to y\) 的变换,然后修改?有问题。

比如 \(1008\),先有一次 \(1\to2\),再有一次 \(0\to1\)。
最终有 \(tag_0=1,tag_1=2\)。
直接暴力改所有 \(i\to tag_i\),这时 \(0\) 会变成 \(2\)。

所以我们在懒标记下传前,先备份当前的 \(tag\) 以及权和。

然后懒标记下传的部分相比暴力改 \(i\to tag_i\) 略有变化。

using ll = long long;

#define rep(i,a,b) for(rg int i = (a);i <= (b);++i)
#define rg register
#define il inline

const int N = 1e5 + 5,S = N << 2;

int n,m;

ll T[10][S],tmp[2][10];
char tg[10][S],old[2][10];

#define lc (i << 1)
#define rc (lc | 1)
#define mid ((L + R) >> 1)

#define ls lc,L,mid
#define rs rc,mid + 1,R
#define id rg int i = 1,rg int L = 1,rg int R = n

il void psu(int i){
	rep(d,0,9) T[d][i] = T[d][lc] + T[d][rc];
}

il void psd(rg int i){
	rep(d,0,9){
		tmp[0][d] = T[d][lc];
		tmp[1][d] = T[d][rc];
		old[0][d] = tg[d][lc];
		old[1][d] = tg[d][rc];
	}
	rep(d,0,9) if(tg[d][i] != d){
		int x = d,y = tg[d][i];
		T[y][lc] += tmp[0][x]; T[x][lc] -= tmp[0][x];
		rep(d,0,9) if(old[0][d] == x) tg[d][lc] = y;
		T[y][rc] += tmp[1][x]; T[x][rc] -= tmp[1][x];
		rep(d,0,9) if(old[1][d] == x) tg[d][rc] = y;
		tg[d][i] = d;
	}
}

il void build(id){
	rep(d,0,9) tg[d][i] = d;
	if(L == R){
		int x = read(),cur = 1;
		while(x){
			T[x % 10][i] += cur;
			x /= 10; cur *= 10;
		}
		return;
	}
	build(ls); build(rs); psu(i);
}

il void upd(rg int l,rg int r,rg int x,rg int y,id){
	if(l <= L && R <= r){
		T[y][i] += T[x][i]; T[x][i] = 0;
		rep(d,0,9) if(tg[d][i] == x) tg[d][i] = y;
		return;
	}
	psd(i);
	if(l <= mid) upd(l,r,x,y,ls);
	if(r > mid) upd(l,r,x,y,rs);
	psu(i);
}

il ll qry(rg int l,rg int r,id){
	if(l <= L && R <= r){
		ll res = 0;
		rep(d,0,9) res += T[d][i] * d;
		return res;
	}
	psd(i);
	return (l <= mid ? qry(l,r,ls) : 0LL) + (r > mid ? qry(l,r,rs) : 0LL);
}

int main(){
	n = read(),m = read();
	build();
	while(m--){
		int op = read(),l = read(),r = read();
		if(op == 2) printf("%lld\n",qry(l,r));
		else { int x = read(),y = read(); if(x != y) upd(l,r,x,y); }
	}
	return 0;
}

标签:lc,int,tag,read,CF794F,rg,tg
来源: https://www.cnblogs.com/zeno6174/p/CF794F.html