題意
個字符串,在區間每個字符串兩端加上一個字符,並求數字和(加的數字都是單位())。
題解
首先要知道,對於單個數。
加上,。
區間就是,
需要維護的信息
考慮用線段樹,需要:
1、維護區間和
2、維護左邊的的次方和
爲了維護操作,我們還需要:
維護左邊的的和[]
維護當前加了幾次(用於)[]
維護右邊的和[]
對於,原串爲,加上和。
右邊的信息則是,;
左邊的信息則是,;
增加的信息是,
這三個都是懶標記。
如何維護
真正難點是兩種情況:
1、同一區間加兩次:
加兩次
左邊就是要很多位,只有已有的部分信息不用考慮,新加入的要考慮:
右邊的就是普通的和:
2、不同區間但是有先後關係:
先小區間,再選上一層區間,要保證傳到的信息正確。
傳遞的時候也需要注意(注意原來有的情況如何增加新的信息):
這些都完成了之後,對的更新即爲:
總結
我死在了左邊信息不考慮右邊位數那一步,我一開始了考慮了右邊位數,但是這樣很難維護傳遞的部分,這樣寫不僅好寫還不容易錯。
#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);
}
}
}
}