题目
大意:给出一个长度为n的序列a,支持如下两个操作
1: 给[l,r]区间加上一个首项为val,公差为d的等差数列。
2: 询问[l,r]区间的和。
思路:利用线段树维护区间的首项(l处的值),公差。原题中还有一个取模:可能的模数m为25以内的素数,那么可以把所有数先对35。。1923取模,最后计算完再对m取模。
维护线段树时需要pushdown()函数,如果不用则要像区间加固定数一样记录祖先的影响,不太容易。同时查询时也要pushdown,因为影响是不可抵消的。
敲代码时还是得看一看屏幕,又在if语句后面多敲了个;,调了半天。
//please ac
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=4*2e5+5;
const ll mod=111546435;
ll sum[maxn],d[maxn],st[maxn];
int a[maxn/4];
int ql,qr;
void build_tree(int o,int l,int r)
{
if(r<=l)
{
sum[o]=a[l]%mod;
return;
}
int lc=2*o,rc=2*o+1,mid=l+(r-l)/2;
build_tree(lc,l,mid);
build_tree(rc,mid+1,r);
sum[o]=(sum[lc]+sum[rc])%mod;
}
void maintain(int o,int l,int r)
{
int lc=2*o,rc=2*o+1,len=r-l+1;
if(l<r)
{
sum[o]=0;
sum[o]=(sum[lc]+sum[rc])%mod;
}
else sum[o]=a[l];
if(st[o]>=0)
sum[o]+=len*st[o]%mod+1ll*len*(len-1)/2%mod*d[o]%mod;
sum[o]%=mod;
}
void pushdown(int o,int l,int r)
{
if(r<=l) return;
int lc=2*o,rc=2*o+1;
int mid=l+(r-l)/2;
if(st[o]>=0)
{
if(st[lc]<0) st[lc]=0;
if(st[rc]<0) st[rc]=0;
st[lc]+=st[o];st[lc]%=mod;
st[rc]+=(st[o]+(mid+1-l)*d[o]%mod)%mod;
st[rc]%=mod;
st[o]=-1;
d[lc]=(d[lc]+d[o])%mod;
d[rc]=(d[rc]+d[o])%mod;
d[o]=0;
}
}
void update(int o,int l,int r,int val,int c)
{
int lc=2*o,rc=2*o+1;
int mid=l+(r-l)/2;
if(ql<=l&&qr>=r)
{
if(st[o]<0) st[o]=0;
st[o]=((st[o]+val)%mod+1ll*(l-ql)*c%mod)%mod;
d[o]=(d[o]+c)%mod;
}
else
{
pushdown(o,l,r);
if(mid>=ql) update(lc,l,mid,val,c);
else maintain(lc,l,mid);
if(mid<qr) update(rc,mid+1,r,val,c);
else maintain(rc,mid+1,r);
}
maintain(o,l,r);
}
ll ans=0;
void query(int o,int l,int r)
{
if(l>=ql&&r<=qr)
{
maintain(o,l,r);
ans+=sum[o];
ans%=mod;
return;
}
int lc=2*o,rc=2*o+1;
int mid=l+(r-l)/2;
pushdown(o,l,r);
if(mid>=ql) query(lc,l,mid);
else maintain(lc,l,mid);
if(qr>mid) query(rc,mid+1,r);
else maintain(rc,mid+1,r);
maintain(o,l,r);
}
int main()
{
//freopen("tte.txt","r",stdin);
memset(st,-1,sizeof(st));
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]%=mod;
}
build_tree(1,1,n);
int q;scanf("%d",&q);
while(q--)
{
int op;scanf("%d",&op);
if(op==1)
{
int val,c;
scanf("%d%d%d%d",&ql,&qr,&val,&c);
update(1,1,n,val,c);
}
else
{
int m;
scanf("%d%d%d",&ql,&qr,&m);
ans=0;
query(1,1,n);
printf("%lld\n",ans%m);
}
}
return 0;
}