线段树基础题
看到有大佬写了splay.....orz%%
二维标记下传,注意下传的顺序就好了
/**************************************************************
Problem: 1798
User: syh0313
Language: C++
Result: Accepted
Time:4836 ms
Memory:17700 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using
namespace
std;
const
int
maxn=100010;
int
n,m,root,topt;
long
long
v[maxn],mo;
struct
da{
int
lc,rc,l,r;
long
long
mul,add,sum;}a[4*maxn];
inline
void
updata(
int
n){a[n].sum=(a[lch].sum+a[rch].sum)%mo;}
void
build_tree(
int
&n,
int
l,
int
r)
{
n=++topt; a[n].add=0; a[n].mul=1; a[n].sum=0; a[n].l=l; a[n].r=r;
if
(l==r) {a[n].sum=v[l]%mo;
return
;}
int
mid=(l+r)>>1;
build_tree(lch,l,mid); build_tree(rch,mid+1,r);
updata(n);
}
void
pushdown(
int
n)
{
if
(a[n].mul!=1)
{
a[lch].sum=a[lch].sum*a[n].mul%mo;
a[lch].add=a[lch].add*a[n].mul%mo;
a[lch].mul=a[lch].mul*a[n].mul%mo;
a[rch].sum=a[rch].sum*a[n].mul%mo;
a[rch].add=a[rch].add*a[n].mul%mo;
a[rch].mul=a[rch].mul*a[n].mul%mo;
a[n].mul=1;
}
if
(a[n].add)
{
a[lch].add=(a[lch].add+a[n].add)%mo;
a[lch].sum=(a[lch].sum+a[n].add*(a[lch].r-a[lch].l+1)%mo)%mo;
a[rch].add=(a[rch].add+a[n].add)%mo;
a[rch].sum=(a[rch].sum+a[n].add*(a[rch].r-a[rch].l+1)%mo)%mo;
a[n].add=0;
}
}
void
tree_add(
int
n,
int
L,
int
R,
int
l,
int
r,
long
long
k)
{
if
(L==l && R==r)
{
a[n].sum=(a[n].sum+k*(r-l+1)%mo)%mo;
a[n].add=(a[n].add+k)%mo;
return
;
}
int
mid=(L+R)>>1; pushdown(n);
if
(r<=mid) tree_add(lch,L,mid,l,r,k);
else
if
(l>=mid+1) tree_add(rch,mid+1,R,l,r,k);
else
tree_add(lch,L,mid,l,mid,k),tree_add(rch,mid+1,R,mid+1,r,k);
updata(n);
}
void
tree_mul(
int
n,
int
L,
int
R,
int
l,
int
r,
long
long
k)
{
if
(L==l && R==r)
{
a[n].sum=a[n].sum*k%mo;
a[n].add=a[n].add*k%mo;
a[n].mul=a[n].mul*k%mo;
return
;
}
int
mid=(L+R)>>1; pushdown(n);
if
(r<=mid) tree_mul(lch,L,mid,l,r,k);
else
if
(l>=mid+1) tree_mul(rch,mid+1,R,l,r,k);
else
tree_mul(lch,L,mid,l,mid,k),tree_mul(rch,mid+1,R,mid+1,r,k);
updata(n);
}
long
long
qury(
int
n,
int
L,
int
R,
int
l,
int
r)
{
if
(L==l && R==r)
return
a[n].sum;
int
mid=(L+R)>>1; pushdown(n);
if
(r<=mid)
return
qury(lch,L,mid,l,r);
else
if
(l>=mid+1)
return
qury(rch,mid+1,R,l,r);
else
return
(qury(lch,L,mid,l,mid)+qury(rch,mid+1,R,mid+1,r))%mo;
updata(n);
}
int
main()
{
scanf
(
"%d%lld"
,&n,&mo);
for
(
int
i=1;i<=n;i++)
scanf
(
"%lld"
,&v[i]);
build_tree(root,1,n);
scanf
(
"%d"
,&m);
while
(m--)
{
int
ff,xx,yy;
long
long
kk;
scanf
(
"%d%d%d"
,&ff,&xx,&yy);
if
(ff==1)
scanf
(
"%lld"
,&kk),tree_mul(root,1,n,xx,yy,kk);
else
if
(ff==2)
scanf
(
"%lld"
,&kk),tree_add(root,1,n,xx,yy,kk);
else
if
(ff==3)
printf
(
"%lld\n"
,qury(root,1,n,xx,yy));
}
return
0;
}