成都磨子桥技工学校 / 数据结构 Challenge 4

描述

给一个长为N的数列,有M次操作,每次操作时以下三种之一:

(1)修改数列中的一个数

(2)求数列中某连续一段所有数的两两乘积的和 mod 1000000007

(3)求数列中某连续一段所有相邻两数乘积的和 mod 1000000007

1<=N<=10^5,1<=M<=10^5,输入保证合法,且所有整数可用带符号32位整型存储。

题解

比较简单,主要是维护第二个信息觉得有点意思,现在已经知道两个小区间内每个元素乘积和,那么合并之后增加的就是来自两个区间的元素的乘积,很容易想到乘法分配律,只要维护区间和即可。还有就是取模恶心到我了,模了之后在外面玩随便查错才发现查询有个小地方写错了(哭了)。

#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);
    }
  }
}
View Code
原文地址:https://www.cnblogs.com/sto324/p/11379898.html