Problem Description
The Fool comes to a cross-road, filled with energy, confidence and purpose, knowing exactly where he wants to go and what he wants to do. But he comes to a dead stop. A flowering tree marks the path he wants to take, the one he’s been planning on taking. But standing before a fruit tree marking the other path is a woman. The Fool has met and had relationships with women before, some far more beautiful and alluring. But she is different. Seeing her, he feels as though he’s just been shot in the heart with cupid’s arrow.
There are
n
n
n empty strings:
s
1
,
s
2
,
.
.
.
,
s
n
s_1, s_2, . . . , s_n
s1,s2,...,sn.
You are required to perform two kinds of operations:
wrap l r d
: change
s
i
s_i
si to
d
s
i
d
ds_id
dsid for all
l
≤
i
≤
r
l ≤ i ≤ r
l≤i≤r, where
d
d
d is a digit character.
query l r
: query
∑
i
=
l
r
v
a
l
u
e
(
s
i
)
(
m
o
d
1
0
9
+
7
)
\sum_{i=l}^r value(s_i) (mod 10^9 + 7)
∑i=lrvalue(si)(mod109+7), where value(s) is the number that string
s
s
s represents.
Note that the value of an empty string is
0
0
0.
Input
The first line contains one integer T, which denote the number of cases.
For each case, the first line contains two integer n and m where
n
n
n is the number of strings and
m
m
m is the number of operations.
Each line of the following m lines contains an operation with format :
wrap l r d
or
query l r
Output
For each case, you should output "Case i:"in a line, where i is the case number starting from 1.
Then for each query operation in that case, output a line that contains a single integer that representing the answer for that query operation.
Sample Input
2
3 2
wrap 1 3 1
query 1 2
4 4
wrap 1 3 0
wrap 2 4 3
query 1 4
query 2 3
Sample Output
Case 1:
22
Case 2:
6039
6006
Hint
1 ≤ T ≤ 5, 1 ≤ n, m ≤ 1e5, 1 ≤ l ≤ r ≤ n.
题意:
给定一个长度为
n
(
n
<
=
1
0
5
)
n(n<=10^5)
n(n<=105),初始全是空串的字符串序列s,有两种操作,第一个操作是给区间里面所有的字符串的头尾加上一个数字d(0~9),第二个操作时询问一个区间里面所有字符串转为数字之后的区间和,对
1
0
9
+
7
10^9+7
109+7取模。
题解:
线段树
记录以下值:
len:
∑
i
=
l
r
1
0
l
e
n
g
t
h
(
s
i
)
+
1
\sum_{i=l}^r 10^{length(s_i)+1}
∑i=lr10length(si)+1
w:
∑
i
=
l
r
s
i
\sum_{i=l}^r s_i
∑i=lrsi
taglen:len的lazy标记
tagl:在这个区间中,左边位置放数字的lazy标记
tagr:在这个区间中,右边位置放置数字的lazy标记
我们知道,对于一个区间来说,在所有字符串左右增加d的操作是修改w
w
=
w
∗
10
+
d
∗
(
r
−
l
+
1
)
+
d
∗
l
e
n
w = w*10+d*(r-l+1)+d*len
w=w∗10+d∗(r−l+1)+d∗len
下传标记的时候要注意以下情况
tagl 为变为
t
a
g
l
+
l
e
n
∗
L
tagl + len*L
tagl+len∗L (L为父节点的tagl)
tagr 为变为
t
a
g
r
∗
L
+
R
tagr*L + R
tagr∗L+R (R为父节点的tagr)
w
=
R
∗
(
r
−
l
+
1
)
+
w
∗
t
l
+
L
∗
t
l
∗
l
e
n
/
10
w = R*(r-l+1)+w*tl+L*tl*len/10
w=R∗(r−l+1)+w∗tl+L∗tl∗len/10(tl为父节点的taglen) 要记得除以10
#include<bits/stdc++.h>
#define ll long long
#define MOD 1000000007LL
using namespace std;
int n,m;
ll ovc;
ll tin(ll y){
if(y==0)return 1;
ll temp=tin(y>>1);
if(y&1){
return (((temp*temp)%MOD)*10LL)%MOD;
}
else return (temp*temp)%MOD;
}
struct seg{
int l,r;
ll len,w,tagl,tagr,taglen;
}tr[400004];
void update(int k){
tr[k].w=(tr[k<<1].w+tr[k<<1|1].w)%MOD;
tr[k].len=(tr[k<<1].len+tr[k<<1|1].len)%MOD;
}
void build(int k,int l,int r){
tr[k].l=l;tr[k].r=r;
tr[k].tagl=0;tr[k].tagr=0;tr[k].w=0;tr[k].taglen=1;
if(l==r){
tr[k].len=10;
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
update(k);
}
void fut(int k,ll L,ll R,ll tl){
int l=tr[k].l,r=tr[k].r;
tr[k].tagl+=(L*tr[k].taglen)%MOD;
tr[k].tagl%=MOD;
tr[k].tagr*=tl;
tr[k].tagr%=MOD;
tr[k].tagr=(tr[k].tagr+R)%MOD;
tr[k].taglen=(tr[k].taglen*tl)%MOD;
tr[k].w=((R*(r-l+1))%MOD+(tr[k].w*tl)%MOD+(((((L*tl)%MOD)*tr[k].len)%MOD)*ovc)%MOD)%MOD;
tr[k].len=(((tr[k].len*tl)%MOD)*tl)%MOD;
}
void pushdown(int k){
ll tl=tr[k].taglen,L=tr[k].tagl,R=tr[k].tagr;
if(tr[k].taglen<=1)return ;
tr[k].taglen=1;
tr[k].tagl=0;
tr[k].tagr=0;
fut(k<<1,L,R,tl);
fut(k<<1|1,L,R,tl);
}
void wrap(int k,int a,int b,ll d){
int l=tr[k].l,r=tr[k].r;
if(a==l&&b==r){
ll al=(d*(r-l+1))%MOD;
ll ar=(d*tr[k].len)%MOD;
tr[k].w=(tr[k].w*10LL)%MOD;
tr[k].w=(tr[k].w+((al+ar)%MOD))%MOD;
tr[k].len=(tr[k].len*100LL)%MOD;
tr[k].tagl+=(d*tr[k].taglen)%MOD;
tr[k].tagl%=MOD;
tr[k].tagr=(tr[k].tagr*10LL)%MOD;
tr[k].tagr=(tr[k].tagr+d)%MOD;
tr[k].taglen*=10LL;
tr[k].taglen%=MOD;
return ;
}
pushdown(k);
int mid=(l+r)>>1;
if(b<=mid)wrap(k<<1,a,b,d);
else if(a>mid)wrap(k<<1|1,a,b,d);
else{
wrap(k<<1,a,mid,d);
wrap(k<<1|1,mid+1,b,d);
}
update(k);
}
ll query(int k,int a,int b){
int l=tr[k].l,r=tr[k].r;
if(l==a&&r==b)return tr[k].w;
pushdown(k);
int mid=(l+r)>>1;
if(b<=mid)return query(k<<1,a,b)%MOD;
else if(a>mid)return query(k<<1|1,a,b)%MOD;
else {
return (query(k<<1,a,mid)+query(k<<1|1,mid+1,b))%MOD;
}
}
void w33ha(int CASE){
scanf("%d%d",&n,&m);
printf("Case %d:\n",CASE);
build(1,1,n);
while(m--){
char s[14];
scanf("%s",s+1);
int l,r;
ll d;
if(s[1]=='w'){
scanf("%d%d%lld",&l,&r,&d);
wrap(1,l,r,d);
}
if(s[1]=='q'){
scanf("%d%d",&l,&r);
printf("%lld\n",query(1,l,r));
}//cout<<"ppp---|"<<tr[4].w<<endl;
}
}
int main(){
int T;scanf("%d",&T);
ovc=tin(MOD-2);
for(int i=1;i<=T;i++)w33ha(i);
return 0;
}