参考:https://blog.csdn.net/qq_31411163/article/details/96345031
题意:给定n个空串,2种操作。把l r上的数前后都加上x;查询l r上数之和。
题解:维护sum1 sum2,以及左右标记和长度标记。维护过程详见代码。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
const int maxn=100010;
const int mod=1e9+7;
ll sum1[maxn<<2];//mark sum of a[i](l<=i<=r)
ll sum2[maxn<<2];//mark sum of 10^(len(a[i]))(l<=i<=r)
ll lazy1[maxn<<2];//左标记
ll lazy2[maxn<<2];//右标记
ll lazy3[maxn<<2];//长度标记
int n,m;
/*
sum1[rt]=(sum1[lson]+sum1[rson])
sum2[rt]=(sum2[lson]+sum2[rson])
*/
void pushup(int rt){
sum1[rt]=(sum1[lson]+sum1[rson])%mod;
sum2[rt]=(sum2[lson]+sum2[rson])%mod;
return;
}
/*
sum1[lson]=sum1[lson]*lazy3[rt]+lazy2[rt]*(m-l+1)+lazy1[rt]*sum2[lson]*lazy3[rt];
sum1[rson]=sum1[rson]*lazy3[rt]+lazy2[rt]*(r-m)+lazy1[rt]*sum2[rson]*lazy3[rt];
sum2[lson]=sum2[lson]*lazy3[rt]*lazy3[rt];//
sum2[rson]=sum2[rson]*lazy3[rt]*lazy3[rt];//
lazy1[lson]=lazy1[lson]+lazy1[rt]*lazy3[lson];
lazy2[lson]=lazy2[lson]*lazy3[rt]+lazy2[rt];
lazy3[lson]=lazy3[lson]*lazy3[rt];
lazy1[rson]=lazy1[rson]+lazy1[rt]*lazy3[rson];
lazy2[rson]=lazy2[rson]*lazy3[rt]+lazy2[rt];
lazy3[rson]=lazy3[rson]*lazy3[rt];
lazy1[rt]=lazy2[rt]=0;
lazy3[rt]=1;
*/
void pushdown(int rt,int l,int r){
if(lazy3[rt]==1) return;
int m=(l+r)>>1;
ll x=lazy1[rt],y=lazy2[rt],z=lazy3[rt];
sum1[lson]=((sum1[lson]*z%mod+y*(m-l+1)%mod)%mod+x*sum2[lson]%mod*z%mod)%mod;
sum1[rson]=((sum1[rson]*z%mod+y*(r-m)%mod)%mod+x*sum2[rson]%mod*z%mod)%mod;
sum2[lson]=sum2[lson]*z%mod*z%mod;//
sum2[rson]=sum2[rson]*z%mod*z%mod;//
lazy1[lson]=(lazy1[lson]+x*lazy3[lson]%mod)%mod;
lazy1[rson]=(lazy1[rson]+x*lazy3[rson]%mod)%mod;
lazy2[lson]=(lazy2[lson]*z%mod+y)%mod;
lazy2[rson]=(lazy2[rson]*z%mod+y)%mod;
lazy3[lson]=lazy3[lson]*z%mod;
lazy3[rson]=lazy3[rson]*z%mod;
lazy1[rt]=lazy2[rt]=0;
lazy3[rt]=1;
}
void build(int rt,int l,int r){
//一开始把lazy标记放l r里面了,debug了5小时。。太久没碰线段树的后果么
lazy1[rt]=0;lazy2[rt]=0;
lazy3[rt]=1;
if(l==r){
sum1[rt]=0;sum2[rt]=1;
return;
}
int m=(l+r)>>1;
build(lson,l,m);
build(rson,m+1,r);
pushup(rt);
}
/*
sum1=sum1*10+sum2*val*10+val*(r-l+1)
sum2=sum2*100
lazy2=lazy2*10+val
lazy1=lazy1+lazy3*val
lazy3=lazy3*10
*/
void update(int rt,int l,int r,int a,int b,int val){
if(l>=a&&r<=b){
sum1[rt]=(sum1[rt]*10%mod+sum2[rt]*val%mod*10%mod+val*(r-l+1)%mod);
sum2[rt]=sum2[rt]*100%mod;
lazy2[rt]=(lazy2[rt]*10%mod+val)%mod;
lazy1[rt]=(lazy1[rt]+lazy3[rt]*val%mod)%mod;
lazy3[rt]=lazy3[rt]*10%mod;
return;
}
pushdown(rt,l,r);
int m=(l+r)>>1;
if(a<=m) update(lson,l,m,a,b,val);
if(m<b) update(rson,m+1,r,a,b,val);
pushup(rt);
}
ll query(int rt,int l,int r,int a,int b){
if(l>=a&&r<=b) return sum1[rt];
pushdown(rt,l,r);
int m=(l+r)>>1;
ll ans=0;
if(a<=m) ans=query(lson,l,m,a,b);
if(m<b) ans=(ans+query(rson,m+1,r,a,b))%mod;
return ans;
}
int main(){
int t;scanf("%d",&t);
int cas=1;
while(t--){
scanf("%d%d",&n,&m);
build(1,1,n);
int l,r,val;
char s[10];
printf("Case %d:\n",cas++);
for(int i=1;i<=m;i++){
scanf("%s%d%d",s,&l,&r);
if(s[0]=='q'){
ll ans;
ans=query(1,1,n,l,r);
//ans=query2(1,1,n,l,r);
printf("%I64d\n",ans);
}else{
scanf("%d",&val);
update(1,1,n,l,r,val);
//update2(1,1,n,l,r,val);
}
}
}
return 0;
}