# BZOJ1798 维护序列seq

## 1798: [Ahoi2009]Seq 维护序列seq

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 8058  Solved: 2964
[Submit][Status][Discuss]

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

## Sample Output

2
35
8

板子题了，用sum数组来存这颗树，每次插入操作对树上的每一段区间/节点都进行一次update

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 8e5+5;
long long mod;
long long n,m;
struct segtree{
#define lc(x) (x*2)
#define rc(x) (x*2+1)
long long l[maxn],r[maxn];
void build(int x,int L,int R){
//数组从1开始
l[x]=L;
r[x]=R;
mul[x]=1;
if(L==R){
//区间节点
cin>>sumi[x];
return;
}
int mid=(L+R)/2;
build(lc(x),L,mid);
build(rc(x),mid+1,R);
update(x);
}
void update(int x){
sumi[x]=(sumi[lc(x)]+sumi[rc(x)])%mod;
}
void push(int x){
mul[lc(x)]=(mul[lc(x)]*mul[x])%mod;
mul[rc(x)]=(mul[rc(x)]*mul[x])%mod;
sumi[lc(x)]=(sumi[lc(x)]*mul[x]+
sumi[rc(x)]=(sumi[rc(x)]*mul[x]+
mul[x]=1;
}
void ADD(int x,int L,int R,long long v){
push(x);
if(R<l[x]||L>r[x]) return;   //查询区间不在范围内
if(L<=l[x]&&r[x]<=R){
sumi[x]=(sumi[x]+v*(r[x]-l[x]+1))%mod;
return;
}
update(x);
}
void MUL(int x,int L,int R,long long v){
push(x);
if(R<l[x]||L>r[x]) return;
if(L<=l[x]&&r[x]<=R){
sumi[x]=(sumi[x]*v)%mod;
mul[x]=(mul[x]*v)%mod;
return;
}
MUL(lc(x),L,R,v);
MUL(rc(x),L,R,v);
update(x);
}
long long Qsum(int x,int L,int R){
push(x);
if(l[x]>R||r[x]<L) return 0;
if(L<=l[x]&&r[x]<=R) return sumi[x];
return (Qsum(lc(x),L,R)+Qsum(rc(x),L,R))%mod;
}
}seg;

int main(){
cin>>n>>mod;
seg.build(1,1,n);
cin>>m;
for(long long i= 1,op,l,r;i<=m;i++){
cin>>op>>l>>r;
if(op==3) {
cout<<seg.Qsum(1,l,r)<<endl;
}
else{
long long v;
cin>>v;
if(op==1) seg.MUL(1,l,r,v);
}