题目描述
给出序列 a1,a2,…an(0≤ai≤109),有关序列的四种操作:
1. al,al+1,…,ar(1≤l≤r≤n)加上 x(-103≤x≤103)
2. al,al+1,…,ar(1≤l≤r≤n)乘上 x(-103≤x≤103)
3. al,al+1,…,ar(1≤l≤r≤n)变成 x-al,x-al+1 ,…,x-ar(-103≤x≤103)
4. 求:
(即求:al+al+1+al+2+…+ar(1≤l≤r≤n)
所有操作均模 109+7
输入格式
第一行包含两个数 n(1≤n≤105)和 m(1≤m≤105),表示序列长度和操作次数
接下来一行包含 n 个数,空格隔开,表示 a1,a2,…,an 。
接下来 m 行,每行为以下 4 种格式之一:
- 0 l r x ,表示 al,al+1,…,ar 加上 x
- 1 l r x ,表示 al,al+1,…,ar 乘上 x
- 2 l r x ,表示 al,al+1,…,ar(1≤l≤r≤n)变成x-al,x-al+1 ,…,x-ar 。
- 3 l r ,求:
输出格式
对于每次询问,输出单独一行表示答案。
样例数据 1
输入
5 4
1 2 3 4 5
0 1 5 1
1 1 5 -1
2 1 5 1
3 5 5
输出
7
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int Max=100010;
const int mod=1e9+7;
int n,m,ans;
int num[Max];
LL add[Max<<2],mul[Max<<2],sum[Max<<2];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void update(LL root) {sum[root] = (LL)(sum[root<<1] + sum[root<<1|1])%mod;}
inline void build(int root,int l,int r)
{
if(l==r) {sum[root] = num[l],mul[root] = 1;return;}
int mid = l + r >> 1;
mul[root] = 1;
build(root<<1,l,mid),build(root<<1|1,mid+1,r);
update(root);
}
inline void pushdown(int root,int l,int r,int mid)
{
if(mul[root] != 1)
{
sum[root<<1] = (LL)(sum[root<<1] * mul[root])%mod;
sum[root<<1|1] = (LL)(sum[root<<1|1] * mul[root])%mod;
add[root<<1] = (LL)(add[root<<1]*mul[root])%mod,add[root<<1|1] = (LL)(add[root<<1|1]*mul[root])%mod;
mul[root<<1] = (LL)(mul[root<<1]*mul[root])%mod,mul[root<<1|1] = (LL)(mul[root<<1|1]*mul[root])%mod;
mul[root] = 1;
}
if(add[root] != 0)
{
sum[root<<1] = (LL)(sum[root<<1] + (mid-l+1) * add[root])%mod;
sum[root<<1|1] = (LL)(sum[root<<1|1] + (r-mid) * add[root])%mod;
add[root<<1] = (LL)(add[root<<1]+add[root])%mod,add[root<<1|1] = (LL)(add[root<<1|1]+add[root])%mod;
add[root] = 0;
}
}
inline void Add(int root,int l,int r,int L,int R,int num)
{
if(L <= l && R >= r) {sum[root] = (LL)(sum[root] += (r-l+1) * num)%mod,add[root] = (add[root]+num)%mod;return;}
int mid = l + r >> 1;
pushdown(root,l,r,mid);
if(L <= mid) Add(root<<1,l,mid,L,R,num);
if(R > mid) Add(root<<1|1,mid+1,r,L,R,num);
update(root);
}
inline void Mul(int root,int l,int r,int L,int R,int num)
{
if(L <= l && R >= r)
{
sum[root] = (LL)(sum[root] * num)%mod;
add[root] = (LL)(add[root] * num)%mod;
mul[root] = (LL)(mul[root] * num)%mod;
return;
}
int mid = l + r >> 1;
pushdown(root,l,r,mid);
if(L <= mid) Mul(root<<1,l,mid,L,R,num);
if(R > mid) Mul(root<<1|1,mid+1,r,L,R,num);
update(root);
}
inline int Q(int root,int l,int r,int L,int R)
{
if(L <= l && R >= r) return sum[root]%mod;
int mid = l + r >> 1;
pushdown(root,l,r,mid);
if(R <= mid) return (LL)Q(root<<1,l,mid,L,R)%mod;
else if(L > mid) return (LL)Q(root<<1|1,mid+1,r,L,R)%mod;
else return (LL)(Q(root<<1,l,mid,L,R) + Q(root<<1|1,mid+1,r,L,R))%mod;
}
int main()
{
n=get_int(),m=get_int();
for(int i=1;i<=n;i++) num[i]=get_int();
build(1,1,n);
for(int i=1;i<=m;i++)
{
int flag = get_int(),L=get_int(),R=get_int();
if(flag == 0)
{
int x=get_int();
Add(1,1,n,L,R,x);
}
if(flag == 1)
{
int x=get_int();
Mul(1,1,n,L,R,x);
}
if(flag == 2)
{
int x=get_int();
Mul(1,1,n,L,R,-1);
Add(1,1,n,L,R,x);
}
if(flag == 3)
{
ans = Q(1,1,n,L,R);
cout<<(ans%mod+mod)%mod<<"\n";
}
}
return 0;
}