线段树题目,维护的信息非常对。
因为我们看到的是区间修改和区间查询,所以可以想到用线段树
现在的要求是往前后插数,求的是数的和。
因此我们可以考虑维护lazy标记往前插的数,往后插的数,和插的位数
并且还要维护答案sum1,以及区间的长度sum2,这是因为区间的长度是不定的,而我们维护区间和的时候,需要乘以区间长度,这个区间长度用10的次方表示
之后就是复杂的讨论,原理很简单,就是右移操作拼接真实的数
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; const int mod=1e9+7; struct node{ int l,r; ll sum1; ll sum2; ll lazy1; ll lazy2; ll lazy3; int st; }tr[N<<2]; void pushup(int u){ tr[u].sum1=(tr[u<<1].sum1+tr[u<<1|1].sum1)%mod; tr[u].sum2=(tr[u<<1].sum2+tr[u<<1|1].sum2)%mod; } void build(int u,int l,int r){ if(l==r){ tr[u]={l,r,0,1,0,0,1,0}; } else{ tr[u]={l,r,0,0,0,0,1,0}; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); pushup(u); } } void pushdown(int u){ tr[u].st=0; ll x=tr[u].lazy1,y=tr[u].lazy2,z=tr[u].lazy3; tr[u].lazy1=tr[u].lazy2=0,tr[u].lazy3=1; tr[u<<1].st=tr[u<<1|1].st=1; tr[u<<1].lazy1=(tr[u<<1].lazy3*x%mod+tr[u<<1].lazy1)%mod; tr[u<<1|1].lazy1=(tr[u<<1|1].lazy3*x%mod+tr[u<<1|1].lazy1)%mod; tr[u<<1].lazy2=(z*tr[u<<1].lazy2+y)%mod; tr[u<<1|1].lazy2=(z*tr[u<<1|1].lazy2+y)%mod; tr[u<<1].lazy3=tr[u<<1].lazy3*z%mod; tr[u<<1|1].lazy3=tr[u<<1|1].lazy3*z%mod; tr[u<<1].sum1=(z*(tr[u<<1].sum2*x%mod+tr[u<<1].sum1)+(tr[u<<1].r-tr[u<<1].l+1)*y%mod)%mod; tr[u<<1|1].sum1=(z*(tr[u<<1|1].sum2*x%mod+tr[u<<1|1].sum1)+(tr[u<<1|1].r-tr[u<<1|1].l+1)*y%mod)%mod; tr[u<<1].sum2=tr[u<<1].sum2*z%mod*z%mod; tr[u<<1|1].sum2=tr[u<<1|1].sum2*z%mod*z%mod; } void modify(int u,int l,int r,int x){ if(tr[u].l>=l&&tr[u].r<=r){ tr[u].st=1; tr[u].lazy2=(10*tr[u].lazy2+x)%mod; tr[u].lazy1=(tr[u].lazy1+x*tr[u].lazy3%mod)%mod; tr[u].lazy3=10*tr[u].lazy3%mod; tr[u].sum1=(10*(tr[u].sum2*x+tr[u].sum1)+(tr[u].r-tr[u].l+1)*x)%mod; tr[u].sum2=100*tr[u].sum2%mod; return ; } if(tr[u].st){ pushdown(u); } int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,x); if(r>mid) modify(u<<1|1,l,r,x); pushup(u); } int query(int u,int l,int r){ if(tr[u].l>=l&&tr[u].r<=r){ return tr[u].sum1; } if(tr[u].st){ pushdown(u); } int mid=tr[u].l+tr[u].r>>1; ll ans=0; if(l<=mid) ans=query(u<<1,l,r); if(r>mid) ans=(ans+query(u<<1|1,l,r))%mod; return ans; } int main(){ ios::sync_with_stdio(false); int t; cin>>t; int cnt=0; while(t--){ int n,m; cin>>n>>m; int i; cnt++; build(1,1,n); cout<<"Case "<<cnt<<":"<<endl; while(m--){ string s; cin>>s; if(s=="wrap"){ int l,r,x; cin>>l>>r>>x; modify(1,l,r,x); } else{ int l,r; cin>>l>>r; cout<<query(1,l,r)<<endl; } } } return 0; }