#6283. 数列分块入门 7
题目:传送门
简要题意:
给出一个长为 n 的数列,以及 n 个操作,操作涉及区间乘法,区间加法,单点询问。
题解:
类似于bzoj的序列维护seq,很想打个线段树...
用分块其实和线段数的操作也是一样的,也就是加两个lazy标记...
要注意的是每次修改的时候,要先将身上的lazy更新到原数列...
码码码码...
代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define mod 10007 #define qread(x) x=read() using namespace std; typedef long long LL; inline LL read() { LL x=0,f=1;char ch; while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return f*x; } LL n,a[110000],lzj[110000],lzc[110000]; LL block,pos[110000]; void add(LL l,LL r,LL c) { if(pos[l]==pos[r]) { for(int i=(pos[l]-1)*block+1;i<=pos[l]*block;i++)a[i]=(a[i]*lzc[pos[l]]+lzj[pos[l]])%mod; lzc[pos[l]]=1;lzj[pos[l]]=0; for(int i=l;i<=r;i++)a[i]=(a[i]+c)%mod; } else { for(int i=pos[l]+1;i<=pos[r]-1;i++)lzj[i]=(lzj[i]+c)%mod; for(int i=(pos[l]-1)*block+1;i<=pos[l]*block;i++)a[i]=(a[i]*lzc[pos[l]]+lzj[pos[l]])%mod; lzj[pos[l]]=0;lzc[pos[l]]=1; for(int i=l;i<=pos[l]*block;i++)a[i]=(a[i]+c)%mod; for(int i=(pos[r]-1)*block+1;i<=pos[r]*block;i++)a[i]=(a[i]*lzc[pos[r]]+lzj[pos[r]])%mod; lzj[pos[r]]=0;lzc[pos[r]]=1; for(int i=(pos[r]-1)*block+1;i<=r;i++)a[i]=(a[i]+c)%mod; } } void multi(LL l,LL r,LL c) { if(pos[l]==pos[r]) { for(int i=(pos[l]-1)*block+1;i<=pos[l]*block;i++)a[i]=(a[i]*lzc[pos[l]]+lzj[pos[l]])%mod; lzc[pos[l]]=1;lzj[pos[l]]=0; for(int i=l;i<=r;i++)a[i]=(a[i]*c)%mod; } else { for(int i=pos[l]+1;i<=pos[r]-1;i++)lzc[i]=(lzc[i]*c)%mod,lzj[i]=(lzj[i]*c)%mod; for(int i=(pos[l]-1)*block+1;i<=pos[l]*block;i++)a[i]=(a[i]*lzc[pos[l]]+lzj[pos[l]])%mod; lzj[pos[l]]=0;lzc[pos[l]]=1; for(int i=l;i<=pos[l]*block;i++)a[i]=(a[i]*c)%mod; for(int i=(pos[r]-1)*block+1;i<=pos[r]*block;i++)a[i]=(a[i]*lzc[pos[r]]+lzj[pos[r]])%mod; lzj[pos[r]]=0;lzc[pos[r]]=1; for(int i=(pos[r]-1)*block+1;i<=r;i++)a[i]=(a[i]*c)%mod; } } int main() { qread(n);for(int i=1;i<=n;i++)qread(a[i]); for(int i=1;i<=n;i++)lzc[i]=1; block=sqrt(n);for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1; for(int i=1;i<=n;i++) { LL opt,l,r,c;qread(opt);qread(l);qread(r);qread(c); if(opt==0)add(l,r,c); else if(opt==1)multi(l,r,c); else printf("%lld ",(a[r]*lzc[pos[r]]+lzj[pos[r]])%mod); } return 0; }