【题目描述】
一个长度为n的序列,一开始序列数的权值都是0,有m次操作
支持两种操作,
1 L R x,给区间[L,R]内位置为pos的数加上(pos-L)*x
0 L R,查询区间[L,R]内的权值和
最终答案对1e9+7取模
【输入格式】
第一行两个数n,m,表示序列长度和操作次数
接下来m行,每行描述一个操作,有如下两种情况:
1 L R x,给区间[L,R]内位置为pos的数加上(pos-L)*x
0 L R,查询区间[L,R]内的权值和
【输出格式】
每一个0操作输出一个整数模1e9+7
【样例输入】
5 5 0 2 3 1 4 5 1 1 1 5 5 0 1 4 0 2 3
【样例输出】
0 30 15
【提示】
对于30%的数据 n,m<=2000
对于100%的数据,n,m<=300000
保证读入的都是非负整数,所有的x<=10000
【来源】
感谢神犇
非常感谢神犇
非常非常感谢神犇
线段树维护等差数列 维护公差与首项
注意取模
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=300000+10;
const long long MOD=1000000007;
long long fr[maxn*4],ad[maxn*4];
long long summ[maxn*4];
typedef long long ll;
ll ql,qr;
inline void pushdown(int o,ll l,ll r){
if(l==r)
return ;
int mid=(l+r)>>1;
fr[o<<1]+=fr[o];
ad[o<<1]+=ad[o];
fr[o<<1]=(fr[o<<1]+MOD)%MOD;
ad[o<<1]=(ad[o<<1]+MOD)%MOD;
summ[o<<1]+=(long long)(fr[o]*(mid-l+1)+MOD)%MOD;
summ[o<<1]=(summ[o<<1]+MOD)%MOD;
summ[o<<1]+=(long long)(((mid-l)*ad[o])*(mid-l+1)/2+MOD)%MOD;
summ[o<<1]=(summ[o<<1]+MOD)%MOD;
fr[o<<1|1]+=fr[o]+ad[o]*(mid+1-l);
ad[o<<1|1]+=ad[o];
fr[o<<1|1]=(fr[o<<1|1]+MOD)%MOD;
ad[o<<1|1]=(ad[o<<1|1]+MOD)%MOD;
summ[o<<1|1]+=(long long)((fr[o]+ad[o]*(mid+1-l))*(r-mid)+MOD)%MOD;
summ[o<<1|1]=(summ[o<<1|1]+MOD)%MOD;
summ[o<<1|1]+=(long long)(((r-mid-1)*ad[o])*(r-mid)/2+MOD)%MOD;
summ[o<<1|1]=(summ[o<<1|1]+MOD)%MOD;
fr[o]=0;
ad[o]=0;
}
inline void add(int o,ll l,ll r,ll x){
if(ad[o])
pushdown(o,l,r);
if(ql<=l&&r<=qr){
fr[o]+=(l-ql)*x;
fr[o]=(fr[o]+MOD)%MOD;
ad[o]+=x;
ad[o]=(ad[o]+MOD)%MOD;
summ[o]+=(long long)(l-ql)*x*(r-l+1);
summ[o]=(summ[o]+MOD)%MOD;
summ[o]+=(long long)((r-l)*x)*(r-l+1)/2;
summ[o]=(summ[o]+MOD)%MOD;
return ;
}
else if(l!=r){
int mid=(l+r)>>1;
if(mid>=ql)
add(o<<1,l,mid,x);
if(mid<qr)
add(o<<1|1,mid+1,r,x);
summ[o]=((summ[o<<1]+summ[o<<1|1])%MOD+MOD)%MOD;
}
}
inline long long query(int o,ll l,ll r){
if(ad[o])
pushdown(o,l,r);
if(ql<=l&&r<=qr)
return (summ[o]+MOD%MOD);
else if(l!=r){
int mid=(l+r)>>1;
long long ans=0;
if(mid>=ql)
ans+=query(o<<1,l,mid);
ans=(ans+MOD)%MOD;
if(mid<qr)
ans+=query(o<<1|1,mid+1,r);
ans=(ans+MOD)%MOD;
return ans;
}
return 0;
}
int main(){
freopen("segment.in","r",stdin);
freopen("segment.out","w",stdout);
int n,m;
scanf("%d %d",&n,&m);
int opt,x;
while(m--){
scanf("%d %d %d",&opt,&ql,&qr);
if(opt==1){
scanf("%d",&x);
add(1,1,n,x);
}
else printf("%lld\n",(query(1,1,n)+MOD)%MOD);
}
return 0;
}