const int maxn=300010;
int a[maxn],ans[maxn<<2],lazy[maxn<<2];
//a为原序列,ans模拟线段树维护区间和,lazy[]为懒惰标记
void build(int p,int l,int r)//建树 build(1,1,n);
{
if (l==r)ans[p]=a[l];
else {
int m=(l+r)>>1;
build(p<<1,l,m);
build(p<<1|1,m+1,r);
ans[p]=ans[p<<1]+ans[p<<1|1];
}
}
void pushdown(int p,int l,int r)
{ //l表示左子树元素结点个数,r表示右子树结点个数
if (lazy[p])
{
lazy[p<<1]+=lazy[p];
lazy[p<<1|1]+=lazy[p];
ans[p<<1]+=lazy[p]*l;
ans[p<<1|1]+=lazy[p]*r;
lazy[p]=0;
}
}
void add(int p,int l,int r,int L,int C)//点更新 add(1,1,n,L,C);
{
if (l==r){ans[p]+=C;return;} //更新结点信息
int m=(l+r)>>1;
//pushdown(p,m-l+1,r-m); 若既有点更新又有区间更新,需要这句话
if (L<=m) add(p<<1,l,m,L,C);
else add(p<<1|1,m+1,r,L,C);
ans[p]=ans[p<<1]+ans[p<<1|1];
}
void update(int p,int l,int r,int L,int R,int C)
{ //区间修改 update(1,1,n,L,R,C);
if (L<=l&&r<=R)
{
ans[p]+=C*(r-l+1);
lazy[p]+=C;
return;
}
int m=(l+r)>>1;
pushdown(p,m-l+1,r-m);
if (L<=m) update(p<<1,l,m,L,R,C);
if (R>m) update(p<<1|1,m+1,r,L,R,C);
ans[p]=ans[p<<1]+ans[p<<1|1];
}
ll query(int p,int l,int r,int L,int R) //区间查询 query(1,1,n,L,R);
{
if (L<=l&&r<=R) return ans[p];
int m=(l+r)>>1;
pushdown(p,m-l+1,r-m);//若更新只有点更新,不需要这句
ll sum=0;
if (L<=m) sum+=query(p<<1,l,m,L,R);
if (R>m) sum+=query(p<<1|1,m+1,r,L,R);
return sum;
}
//单点更新实现区间更新,某些更新次数有限的题目可用
void update(int o,int l,int r,int x,int y)
{
//if(a[o]==(r-l+1))return ;
if(l==r) {
a[o]=sqrt((double)a[o]);
return;
}
int m=(l+r)/2;
int ls=2*o,rs=ls+1;
if(x<=m) update(ls,l,m,x,y); //与单点更新不同之处
if(y>m)update(rs,m+1,r,x,y); //
a[o]=a[ls]+a[rs];
}
双延迟标记
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll a[maxn<<2],t[maxn];
ll add[maxn<<2],mul[maxn<<2];
ll q;
void build(ll p,ll l,ll r)
{
mul[p]=1;add[p]=0;
if(l==r){a[p]=t[l]%q;return ;}
ll m=(l+r)>>1;
build(p<<1,l,m);
build(p<<1|1,m+1,r);
a[p]=(a[p<<1]+a[p<<1|1])%q;
}
void pushdown(int p,int l,int r)
{
a[p<<1]=(a[p<<1]*mul[p]+add[p]*l)%q;
a[p<<1|1]=(a[p<<1|1]*mul[p]+add[p]*r)%q;
mul[p<<1]=(mul[p<<1]*mul[p])%q;
mul[p<<1|1]=(mul[p<<1|1]*mul[p])%q;
add[p<<1]=(add[p<<1]*mul[p]+add[p])%q;
add[p<<1|1]=(add[p<<1|1]*mul[p]+add[p])%q;
mul[p]=1;add[p]=0;
}
void update(ll p,ll l,ll r,ll L,ll R,ll c,ll k)
{
if(L<=l&&R>=r){
if(k==1){
a[p]=(a[p]*c)%q;
mul[p]=(mul[p]*c)%q;
add[p]=(add[p]*c)%q;
}
else if(k==2){
a[p]=(a[p]+c*(r-l+1))%q;
add[p]=(add[p]+c)%q;
}
return ;
}
ll m=(l+r)>>1;
pushdown(p,m-l+1,r-m);
if(L<=m)update(p<<1,l,m,L,R,c,k);
if(R>m)update(p<<1|1,m+1,r,L,R,c,k);
a[p]=(a[p<<1]+a[p<<1|1])%q;
}
ll query(ll p,ll l,ll r,ll L,ll R)
{
if(L<=l&&R>=r)return a[p];
ll m=(l+r)>>1;
pushdown(p,m-l+1,r-m);
ll sum=0;
if(L<=m)sum+=query(p<<1,l,m,L,R);
sum%=q;
if(R>m)sum+=query(p<<1|1,m+1,r,L,R);
sum%=q;
return sum;
}
int main()
{
ll n,m;
scanf("%lld%lld%lld",&n,&m,&q);
for(ll i=1;i<=n;i++)scanf("%lld",&t[i]);
build(1,1,n);
ll a,l,r,c;
while(m--)
{
scanf("%lld%lld%lld",&a,&l,&r);
if(a==1){
scanf("%lld",&c);
update(1,1,n,l,r,c,a);
}
else if(a==2){
scanf("%lld",&c);
update(1,1,n,l,r,c,a);
}
else if(a==3){
ll ans=query(1,1,n,l,r);
printf("%lld\n",ans);
}
}
return 0;
}
模板
inline int lowbit(int x){return x&(-x);}
void update(int x,int d){
while(x<=m){
a[x]+=d;
x+=lowbit(x);
}
}
ll sum(int x){
ll s=0;
while(x>0){
s+=a[x];
x-=lowbit(x);
}
return s;
}