题意:
给你一个数组,初始值为零,有四种操作:
(1)”1 x y c”,代表 把区间 [x,y] 上的值全部加c。
(2)”2 x y c”,代表 把区间 [x,y] 上的值全部乘以c。
(3)”3 x y c” 代表 把区间 [x,y]上的值全部赋值为c。
(4)”4 x y p” 代表 求区间 [x,y] 上值的p次方和1<=p<=3。
分析:
明显是线段树维护的题。
一看只有1~3次方就知道线段树要开3变量分别维护。
这几种更新操作之间会相互影响,比如对一个区间进行操作3之后,那么操作1和2就失效了。因此在PushDown传递懒标记的时候,传递的顺序也是重要的。
一次方:
sum[0]=sum[0]+(r−l+1)∗c
二次方:
∵
(a+b)2=a2+2∗a∗b+b2
∴
sum[1]=sum[1]+2∗c∗sum[0]+(r−l+1)∗c2
(注:此处的sum[0]是未更新前的sum[0])
三次方:
∵
(a+b)3=a3+3∗a2∗b+3∗a∗b2+b3
;
∴
sum[2]=sum[2]+3∗c∗sum[1]+3∗c2∗sum[0]+(r−l+1)∗c3
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1001000,mod=10007;
int n,m,x,y,z,k;
struct tree{long long l,r,sum[4],jia,cheng,lazy;}g[4*N];
long long plus(long long &x,long long y){x=(x+y)%mod;}
void cheng(int rt,int val)
{
if (~g[rt].jia) g[rt].jia=g[rt].jia*val%mod;
if (~g[rt].lazy) g[rt].lazy=g[rt].lazy*val%mod; else
if (~g[rt].cheng) g[rt].cheng=g[rt].cheng*val%mod; else
g[rt].cheng=val;
g[rt].sum[1]=g[rt].sum[1]*val%mod;
g[rt].sum[2]=g[rt].sum[2]*val%mod*val%mod;
g[rt].sum[3]=g[rt].sum[3]*val%mod*val%mod*val%mod;
}
void jia(int rt,int val)
{
int l=g[rt].l,r=g[rt].r;
if (~g[rt].lazy) plus(g[rt].lazy,val); else
if (~g[rt].jia) plus(g[rt].jia,val); else
g[rt].jia=val;
plus(g[rt].sum[3],(r-l+1)*val%mod*val%mod*val%mod);
plus(g[rt].sum[3],3*g[rt].sum[1]*val%mod*val%mod);
plus(g[rt].sum[3],3*g[rt].sum[2]*val%mod);
plus(g[rt].sum[2],(r-l+1)*val%mod*val%mod);
plus(g[rt].sum[2],2*g[rt].sum[1]*val%mod);
plus(g[rt].sum[1],(r-l+1)*val%mod);
}
void lazy(int rt,int val)
{
int l=g[rt].l,r=g[rt].r;
g[rt].lazy=val;
g[rt].jia=g[rt].cheng=-1;
g[rt].sum[1]=(r-l+1)*val%mod;
g[rt].sum[2]=g[rt].sum[1]*val%mod;
g[rt].sum[3]=g[rt].sum[2]*val%mod;
}
void pushup(int rt)
{
g[rt].sum[1]=(g[2*rt].sum[1]+g[2*rt+1].sum[1])%mod;
g[rt].sum[2]=(g[2*rt].sum[2]+g[2*rt+1].sum[2])%mod;
g[rt].sum[3]=(g[2*rt].sum[3]+g[2*rt+1].sum[3])%mod;
}
void pushdown(int rt)
{
if (g[rt].l==g[rt].r) return;
if (~g[rt].cheng) cheng(2*rt,g[rt].cheng),cheng(2*rt+1,g[rt].cheng),g[rt].cheng=-1;
if (~g[rt].jia) jia(2*rt,g[rt].jia),jia(2*rt+1,g[rt].jia),g[rt].jia=-1;
if (~g[rt].lazy) lazy(2*rt,g[rt].lazy),lazy(2*rt+1,g[rt].lazy),g[rt].lazy=-1;
}
void build(int rt,int l,int r)
{
g[rt].l=l,g[rt].r=r;
for (int i=1;i<4;i++)
g[rt].sum[i]=0;
g[rt].jia=g[rt].cheng=g[rt].lazy=-1;
if (l==r) return;
int mid=(l+r)/2;
build(2*rt,l,mid);
build(2*rt+1,mid+1,r);
}
void update(int rt,int ll,int rr,int val,int k)
{
int l=g[rt].l,r=g[rt].r;
if (ll<=l && r<=rr)
{
if (k==1) jia(rt,val);
if (k==2) cheng(rt,val);
if (k==3) lazy(rt,val);
return;
}
pushdown(rt);
int mid=(l+r)/2;
if (ll<=mid) update(2*rt,ll,rr,val,k);
if (rr> mid) update(2*rt+1,ll,rr,val,k);
pushup(rt);
}
long long query(int rt,int ll,int rr,int val)
{
int l=g[rt].l,r=g[rt].r;
if (ll<=l && r<=rr)
return g[rt].sum[val];
pushdown(rt);
long long mid=(l+r)/2,res=0;
if (ll<=mid) res=(res+query(2*rt,ll,rr,val))%mod;
if (rr> mid) res=(res+query(2*rt+1,ll,rr,val))%mod;
return res;
}
int main()
{
while (~scanf("%d%d",&n,&m) && n && m)
{
build(1,1,n);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&k,&x,&y,&z);
if (k==4)
printf("%d\n",query(1,x,y,z)); else
update(1,x,y,z,k);
}
}
return 0;
}