描述
给一个长为N的数列,有M次操作,每次操作时以下三种之一:
(1)修改数列中的一个数
(2)求数列中某连续一段所有数的两两乘积的和 mod 1000000007
(3)求数列中某连续一段所有相邻两数乘积的和 mod 1000000007
1<=N<=10^5,1<=M<=10^5,输入保证合法,且所有整数可用带符号32位整型存储。
题解
比较简单,主要是维护第二个信息觉得有点意思,现在已经知道两个小区间内每个元素乘积和,那么合并之后增加的就是来自两个区间的元素的乘积,很容易想到乘法分配律,只要维护区间和即可。还有就是取模恶心到我了,模了之后在外面玩随便查错才发现查询有个小地方写错了(哭了)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=100005; const int mod=1000000007; int n,m,cnt,root; ll a[maxn]; struct tree{ int ls,rs; ll sum,mul1,mul2;//mul1:区间相邻的数的乘积和 mul2:两两乘积和 ll lnum,rnum; }tr[maxn<<1]; template<class T>inline void read(T &x){ x=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x= f ? -x : x ; } void update(tree &ret,tree lx,tree ry){ ret.lnum=lx.lnum; ret.rnum=ry.rnum; ret.sum=(lx.sum+ry.sum)%mod; ret.mul1=((lx.mul1+ry.mul1)%mod+lx.rnum*ry.lnum%mod)%mod; ret.mul2=((lx.mul2+ry.mul2)%mod+lx.sum*ry.sum%mod)%mod; } void update(int rt){ update(tr[rt],tr[tr[rt].ls],tr[tr[rt].rs]); } void build(int &rt,int l,int r){ rt=++cnt; if(l==r){ ll val=(a[l]%mod+mod)%mod; tr[rt]=(tree){0,0,val,0,0,val,val}; return ; } int mid=(l+r)>>1; build(tr[rt].ls,l,mid); build(tr[rt].rs,mid+1,r); update(rt); } void modify(int rt,int l,int r,int pos,ll val){ if(l==r){ tr[rt]=(tree){0,0,val,0,0,val,val}; return ; } int mid=(l+r)>>1; if(pos<=mid) modify(tr[rt].ls,l,mid,pos,val); else modify(tr[rt].rs,mid+1,r,pos,val); update(rt); } tree query(int rt,int l,int r,int a_l,int a_r){ if(a_l<=l&&r<=a_r) return tr[rt]; int mid=(l+r)>>1; if(a_r<=mid) return query(tr[rt].ls,l,mid,a_l,a_r); if(mid<a_l) return query(tr[rt].rs,mid+1,r,a_l,a_r); tree ret,x,y; x=query(tr[rt].ls,l,mid,a_l,a_r); y=query(tr[rt].rs,mid+1,r,a_l,a_r); update(ret,x,y); return ret; } int main(){ read(n);read(m); for(int i=1;i<=n;i++) read(a[i]); build(root,1,n); for(int i=1;i<=m;i++){ char op[2]; scanf("%s",op); if(op[0]=='M'){ int pos; ll val; read(pos);read(val); val=(val%mod+mod)%mod; modify(1,1,n,pos,val); } else if(op[0]=='Q'){ int l,r; read(l);read(r); printf("%lld ",query(1,1,n,l,r).mul2); } else { int l,r; read(l);read(r); printf("%lld ",query(1,1,n,l,r).mul1); } } }