题意
n n n个字符串,在区间每个字符串两端加上一个字符,并求数字和(加的数字都是单位( 0 → 9 0\to9 0→9))。
题解
首先要知道,对于单个数。
加上
d
d
d,
d
∗
10
∗
1
0
l
e
n
+
s
u
m
+
d
d*10*10^{len}+sum+d
d∗10∗10len+sum+d。
区间就是,
d
∗
10
∗
(
1
0
l
e
n
1
+
1
0
l
e
n
2
+
.
.
.
+
1
0
l
e
n
r
)
+
s
u
m
+
(
d
1
+
d
2
+
.
.
.
+
d
n
)
d*10*(10^{len_1}+10^{len_2}+...+10^{len_r})+sum+(d_1+d_2+...+d_n)
d∗10∗(10len1+10len2+...+10lenr)+sum+(d1+d2+...+dn)
需要维护的信息
考虑用线段树,需要:
1、维护区间和
s
u
m
sum
sum
2、维护左边的
1
0
l
e
n
i
10^{len_i}
10leni的次方和
R
R
R
为了维护
1
1
1操作,我们还需要:
维护左边的
d
d
d的和[
l
a
z
y
r
lazy_r
lazyr]
维护当前加了几次(用于
p
u
s
h
d
o
w
n
pushdown
pushdown)[
a
d
d
add
add]
维护右边的和[
l
a
z
y
d
lazy_d
lazyd]
对于
345543
345543
345543,原串为
55
55
55,加上
4
4
4和
3
3
3。
右边的信息则是
45
45
45,
l
a
z
y
d
=
43
lazy_d=43
lazyd=43;
左边的信息则是
34
34
34,
l
a
z
y
r
=
34
lazy_r=34
lazyr=34;
增加的信息是
2
2
2,
a
d
d
=
2
add=2
add=2
这三个都是懒标记。
如何维护
真正难点是两种情况:
1、同一区间加两次:
[
1
,
2
]
[1,2]
[1,2]加两次
左边就是要很多位,只有已有的
R
R
R部分信息不用考虑,新加入的要考虑:
l
a
z
y
r
=
l
a
z
y
r
+
d
∗
1
0
a
d
d
lazy_r=lazy_r+d*10^{add}
lazyr=lazyr+d∗10add
右边的就是普通的和:
l
a
z
y
d
=
l
a
z
y
d
∗
10
+
d
lazy_d=lazy_d*10+d
lazyd=lazyd∗10+d
2、不同区间但是有先后关系:
先小区间
[
1
,
2
]
[1,2]
[1,2],再选上一层区间
[
1
,
4
]
[1,4]
[1,4],要保证传到
[
1
,
1
]
[1,1]
[1,1]的信息正确。
传递
l
a
z
y
lazy
lazy的时候也需要注意(注意原来有
l
a
z
y
lazy
lazy的情况如何增加新的信息):
l
s
o
n
−
>
l
a
z
y
r
=
l
s
o
n
−
>
l
a
z
y
r
+
l
a
z
y
r
∗
1
0
l
s
o
n
−
>
a
d
d
lson->lazy_r=lson->lazy_r+lazy_r*10^{lson->add}
lson−>lazyr=lson−>lazyr+lazyr∗10lson−>add
l
s
o
n
−
>
l
a
z
y
d
=
l
s
o
n
−
>
l
a
z
y
d
∗
1
0
a
d
d
+
l
a
z
y
d
lson->lazy_d=lson->lazy_d*10^{add}+lazy_d
lson−>lazyd=lson−>lazyd∗10add+lazyd
这些都完成了之后,
p
u
s
h
d
o
w
n
pushdown
pushdown对
s
u
m
sum
sum的更新即为:
s
u
m
=
s
u
m
∗
1
0
a
d
d
+
l
a
z
y
d
+
l
a
z
y
r
∗
R
∗
1
0
a
d
d
sum=sum*10^{add}+lazy_d+lazy_r*R*10^{add}
sum=sum∗10add+lazyd+lazyr∗R∗10add
总结
我死在了左边信息不考虑右边位数那一步,我一开始了考虑了右边位数,但是这样很难维护传递 l a z y lazy lazy的部分,这样写不仅好写还不容易错。
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn = 5e5+510;
const int mod = 1e9+7;
struct tree2{
tree2 *lson,*rson;
ll sum,mr;
ll add,lazy_r,lazy_d;
}dizhi[maxn<<2],*root=&dizhi[0];
int n,m,t=1;
ll A[maxn];
void push_up(tree2 *tree,int l,int r){
tree->sum=(tree->lson->sum+tree->rson->sum)%mod;
tree->mr=(tree->lson->mr+tree->rson->mr)%mod;
}
void push_down(tree2 *tree,int l,int r){
if(!tree->add)return ;
int mid=(l+r)>>1;
tree->lson->sum=(tree->lson->sum*A[tree->add])%mod;
tree->lson->sum=(tree->lson->sum+tree->lson->mr%mod*tree->lazy_r%mod*A[tree->add])%mod;
tree->lson->sum=(tree->lson->sum+1ll*(mid-l+1)*tree->lazy_d%mod)%mod;
tree->rson->sum=(tree->rson->sum*A[tree->add])%mod;
tree->rson->sum=(tree->rson->sum+tree->rson->mr%mod*tree->lazy_r%mod*A[tree->add])%mod;
tree->rson->sum=(tree->rson->sum+1ll*(r-mid)*tree->lazy_d%mod)%mod;//对sum
tree->lson->mr=tree->lson->mr*A[tree->add]%mod*A[tree->add]%mod;
tree->rson->mr=tree->rson->mr*A[tree->add]%mod*A[tree->add]%mod;
tree->lson->lazy_d=(tree->lson->lazy_d*A[tree->add]%mod+tree->lazy_d)%mod;
tree->rson->lazy_d=(tree->rson->lazy_d*A[tree->add]%mod+tree->lazy_d)%mod;
tree->lson->lazy_r=(tree->lson->lazy_r+tree->lazy_r*A[tree->lson->add]%mod)%mod;
tree->rson->lazy_r=(tree->rson->lazy_r+tree->lazy_r*A[tree->rson->add]%mod)%mod;;
tree->lson->add=(tree->add+tree->lson->add)%mod;
tree->rson->add=(tree->add+tree->rson->add)%mod;
tree->add=tree->lazy_d=tree->lazy_r=0;
}
void build(tree2 *tree,int l,int r){
tree->add=tree->lazy_d=tree->lazy_r=0;
if(l==r){
tree->sum=0;
tree->mr=1;
return ;
}
tree->lson=&dizhi[t++];
tree->rson=&dizhi[t++];
int mid=(l+r)>>1;
build(tree->lson,l,mid);
build(tree->rson,mid+1,r);
push_up(tree,l,r);
}
void update(tree2 *tree,int l,int r,int x,int y,int d){
if(x<=l&&r<=y){
tree->sum=(tree->sum*10%mod+1ll*(r-l+1)*d%mod+d*tree->mr%mod*10)%mod;
tree->lazy_d=(tree->lazy_d*10%mod+d)%mod;
tree->lazy_r=(tree->lazy_r+1ll*d*A[tree->add]%mod)%mod;
tree->mr=tree->mr*100%mod;
tree->add++;
// cout<<tree->sum<<" "<<tree->mr<<" "<<tree->lazy_d<<" "<<tree->lazy_r<<endl;
return ;
}
push_down(tree,l,r);
int mid=(l+r)>>1;
if(x<=mid)update(tree->lson,l,mid,x,y,d);
if(y>mid)update(tree->rson,mid+1,r,x,y,d);
push_up(tree,l,r);
}
int query(tree2 *tree,int l,int r,int x,int y){
if(x<=l&&r<=y)return tree->sum;
push_down(tree,l,r);
int mid=(l+r)>>1;
int t1=0,t2=0;
if(x<=mid)t1=query(tree->lson,l,mid,x,y);
if(y>mid)t2=query(tree->rson,mid+1,r,x,y);
return (t1+t2)%mod;
}
int main(){
int T,kase=0;cin>>T;
A[0]=1;
for(int i=1;i<maxn;i++)A[i]=10*A[i-1]%mod;
while(T--){
t=1;
scanf("%d%d",&n,&m);
printf("Case %d:\n",++kase);
build(root,1,n);
for(int i=1;i<=m;i++){
char str[8];scanf("%s",str);
int l,r,d;
if(str[0]=='w'){
scanf("%d%d%d",&l,&r,&d);
update(root,1,n,l,r,d);
}
else{
scanf("%d%d",&l,&r);
ll ans=query(root,1,n,l,r);
printf("%lld\n",ans);
}
}
}
}