CF794F
作者:互联网
口胡十秒钟,调题两小时。
好的其实是个不难的 \(\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