本文主要是介绍2018ccpc吉林 H: LOVERS 线段树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题意:原先有n个空串,两种操作:
题解:对于wrap一个数x的话,那么这个数会变成dxd,这个数的变化过程是d*10^strlen(x)*10+x*10+d,那么我们修改一个区间呢。区间[l,r]也就变化为 d*10*(10^strlen(a[l]) + 10^strlen(a[l+1]).....+ 10^strlen(a[r]) ) + (a[l]+a[l+1]+...+a[r])*10+d*(r-l+1);所以我们可以通过线段树来维护下区间和(我用s1表示的) 和 (10^strlen(a[l]) + 10^strlen(a[l+1]).....+ 10^strlen(a[r]) )(我用s2表示的),然后我又设了laz1和laz2,作为当前区间左右添加的数,用来更新两个子区间,lazlen表示10^strlen(laz1),方便更新子区间。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll mod=1e9+7;
struct node{int l,r,len;ll s1; // lenll s2;ll laz1,laz2,lazlen;
}tree[N<<2];
int n,m;
void build(int l,int r,int cur)
{tree[cur].l=l;tree[cur].r=r;tree[cur].len=r-l+1;tree[cur].laz1=0;tree[cur].laz2=0;tree[cur].lazlen=1;tree[cur].s1=r-l+1;tree[cur].s2=0;if(l==r)return;int mid=(r+l)>>1;build(l,mid,cur<<1);build(mid+1,r,cur<<1|1);
}
void pushdown(int cur)
{if(tree[cur].lazlen>1){ tree[cur<<1].s2=(tree[cur].laz1*tree[cur<<1].s1%mod*tree[cur].lazlen%mod+tree[cur<<1].s2*tree[cur].lazlen%mod+tree[cur].laz2*tree[cur<<1].len%mod)%mod;tree[cur<<1|1].s2=(tree[cur].laz1*tree[cur<<1|1].s1%mod*tree[cur].lazlen%mod+tree[cur<<1|1].s2*tree[cur].lazlen%mod+tree[cur].laz2*tree[cur<<1|1].len%mod)%mod;tree[cur<<1].s1=(tree[cur<<1].s1*tree[cur].lazlen%mod*tree[cur].lazlen)%mod;tree[cur<<1|1].s1=(tree[cur<<1|1].s1*tree[cur].lazlen%mod*tree[cur].lazlen)%mod;tree[cur<<1].laz1=(tree[cur].laz1*tree[cur<<1].lazlen%mod+tree[cur<<1].laz1)%mod;tree[cur<<1|1].laz1=(tree[cur].laz1*tree[cur<<1|1].lazlen%mod+tree[cur<<1|1].laz1)%mod;tree[cur<<1].laz2=(tree[cur<<1].laz2*tree[cur].lazlen%mod+tree[cur].laz2)%mod;tree[cur<<1|1].laz2=(tree[cur<<1|1].laz2*tree[cur].lazlen%mod+tree[cur].laz2)%mod;tree[cur<<1].lazlen=(tree[cur<<1].lazlen*tree[cur].lazlen)%mod;tree[cur<<1|1].lazlen=(tree[cur<<1|1].lazlen*tree[cur].lazlen)%mod;tree[cur].lazlen=1;tree[cur].laz1=0;tree[cur].laz2=0;}
}
void pushup(int cur)
{tree[cur].s1=(tree[cur<<1].s1+tree[cur<<1|1].s1)%mod;tree[cur].s2=(tree[cur<<1].s2+tree[cur<<1|1].s2)%mod;
}
void update(int pl,int pr,int cur,int d)
{
// printf("%d %d - %d\n",tree[cur].l,tree[cur].r,d);if(pl<=tree[cur].l && tree[cur].r<=pr){tree[cur].s2=(d*tree[cur].s1*10%mod+tree[cur].s2*10%mod+tree[cur].len*d%mod)%mod;// cout<<tree[cur].s2<<endl;tree[cur].s1=(tree[cur].s1*100)%mod;tree[cur].laz1=(tree[cur].lazlen*d%mod+tree[cur].laz1)%mod;tree[cur].laz2=(tree[cur].laz2*10+d)%mod;tree[cur].lazlen=(tree[cur].lazlen*10)%mod;
// cout<<tree[cur].s1<<" "<<tree[cur].s2<<" "<<tree[cur].laz1<<" "<<tree[cur].laz2<<" "<<tree[cur].lazlen<<endl;return;}pushdown(cur);if(pl<=tree[cur<<1].r) update(pl,pr,cur<<1,d);if(pr>=tree[cur<<1|1].l) update(pl,pr,cur<<1|1,d);pushup(cur);
}
ll query(int pl,int pr,int cur)
{
// cout<<tree[cur].l<<" "<<tree[cur].r<<" "<<tree[cur].s1<<" "<<tree[cur].s2<<" "<<tree[cur].laz1<<" "<<tree[cur].laz2<<" "<<tree[cur].lazlen<<endl;if(pl<=tree[cur].l&&tree[cur].r<=pr){return tree[cur].s2;}pushdown(cur);ll res=0;if(pl<=tree[cur<<1].r) res+=query(pl,pr,cur<<1);if(pr>=tree[cur<<1|1].l) res+=query(pl,pr,cur<<1|1);return res%mod;
}
int main()
{int T;int nn=1;char op[10];int l,r,d;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);build(1,n,1);printf("Case %d:\n",nn++);while(m--){scanf("%s%d%d",op,&l,&r);if(op[0]=='w'){scanf("%d",&d);update(l,r,1,d);}else{printf("%lld\n",query(l,r,1));}}}return 0;
}
这篇关于2018ccpc吉林 H: LOVERS 线段树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!