Yuanfang is puzzled with the question below:
There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
InputThere are no more than 10 test cases.
There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
OutputFor each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.Sample Input
5 5 3 3 5 7 1 2 4 4 4 1 5 2 2 2 5 8 4 3 5 3 0 0Sample Output
307 7489
这道题有三种询问分别问区间和 平分的区间和 立方的区间和 有三种修改的方法 分别是 add 增加 mul 乘 sett 数值代替
所以要有三个lazy标记 当sett出现时 把 add mul标记都取消 当mul 出现时 如果有add标记 add变为 add*mul
所以在pushdown的过程中 先sett 在mul 最后 add
对于 set 和 mul 来说 平分和 和 立方和比较好求 对于add来说
平方和这样来推:(a + c)2 = a2 + c2 + 2ac , 即sum2[rt] = sum2[rt] + (r - l + 1) * c * c + 2 * sum1[rt] * c;
立方和这样推:(a + c)3 = a3 + c3 + 3a(a2 + ac) , 即sum3[rt] = sum3[rt] + (r - l + 1) * c * c * c + 3 * c * (sum2[rt] + sum1[rt] * c);
几个注意点:add标记取消的时候是置0,mul标记取消的时候是置1;在PushDown()中也也要注意取消标记,如set操作中取消add和mul,mul操作中更新add; 在add操作中要注意sum3 , sum2 , sum1的先后顺序,一定是先sum3 , 然后sum2 , 最后sum1; int容易爆,还是用LL要保险一点;
#include<stdio.h>
#include<string.h>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#include<queue>
#include<deque>
#include<math.h>
#define ll long long
#define ls rt<<1
#define rs rt<<1|1
#define maxn 100000+10
const ll mod=10007;
const int inf=0x3f3f3f3f;
using namespace std;
ll sum1[maxn<<2],sum2[maxn<<2],sum3[maxn<<2];//sum1区间和 sum2 平方和 sum3 立方和
ll add[maxn<<2],mul[maxn<<2],sett[maxn<<2];
void pushup(ll rt)
{
sum1[rt]=(sum1[ls]+sum1[rs])%mod;
sum2[rt]=(sum2[ls]+sum2[rs])%mod;
sum3[rt]=(sum3[ls]+sum3[rs])%mod;
}
void build(ll l,ll r,ll rt) //建立树
{
add[rt]=sett[rt]=0; //初始为0
mul[rt]=1;//初始为1
if(l==r)
{
sum1[rt]=sum2[rt]=sum3[rt]=0;
return ;
}
ll m=(l+r)>>1;
build(l,m,ls);
build(m+1,r,rs);
pushup(rt);
}
void pushdown(ll rt,ll ln,ll rn)//下推标记
{
if(sett[rt]) //存在数值代替
{
sett[rs]=sett[ls]=sett[rt];
add[ls]=add[rs]=0;
mul[ls]=mul[rs]=1;
ll tmp=sett[rt]%mod;
sum1[ls]=((ln%mod)*tmp)%mod;
sum1[rs]=((rn%mod)*tmp)%mod;
tmp=(tmp*tmp)%mod;
sum2[ls]=((ln%mod)*tmp)%mod;
sum2[rs]=((rn%mod)*tmp)%mod;
tmp=(tmp*(sett[rt]%mod))%mod;
sum3[ls]=((ln%mod)*tmp)%mod;
sum3[rs]=((rn%mod)*tmp)%mod;
sett[rt]=0;
}
if(mul[rt]!=1)//mul不为1 说明有过2操作
{
mul[ls]=(mul[ls]*mul[rt])%mod;
mul[rs]=(mul[rs]*mul[rt])%mod;
if(add[ls])
add[ls]=(add[ls]*mul[rt])%mod;
if(add[rs])
add[rs]=(add[rs]*mul[rt])%mod;
ll tmp=mul[rt]%mod;
sum1[ls]=sum1[ls]*tmp%mod;
sum1[rs]=sum1[rs]*tmp%mod;
tmp=tmp*tmp%mod;
sum2[ls]=sum2[ls]*tmp%mod;
sum2[rs]=sum2[rs]*tmp%mod;
tmp=tmp*(mul[rt]%mod)%mod;
sum3[ls]=sum3[ls]*tmp%mod;
sum3[rs]=sum3[rs]*tmp%mod;
mul[rt]=1;
}
if(add[rt])
{
add[ls]+=add[rt];
add[rs]+=add[rt];
ll tmp=((add[rt]%mod)*(add[rt]%mod))%mod*(add[rt]%mod)%mod;
sum3[ls]=(sum3[ls]+((tmp*ln)%mod)+3*add[rt]*((sum2[ls]+(sum1[ls]*add[rt])%mod)%mod))%mod;
sum3[rs]=(sum3[rs]+((tmp*rn)%mod)+3*add[rt]*((sum2[rs]+(sum1[rs]*add[rt])%mod)%mod))%mod;
tmp=(add[rt]%mod)*(add[rt]%mod)%mod;
sum2[ls]=(sum2[ls]+((tmp*ln)%mod)+2*((sum1[ls]*add[rt])%mod))%mod;
sum2[rs]=(sum2[rs]+((tmp*rn)%mod)+2*((sum1[rs]*add[rt])%mod))%mod;
sum1[ls]=(sum1[ls]+(add[rt]*ln)%mod)%mod;
sum1[rs]=(sum1[rs]+(add[rt]*rn)%mod)%mod;
add[rt]=0;
}
}
void update(ll L,ll R,ll l,ll r,ll rt,ll c,ll x)
{
if(L<=l&&r<=R)
{
if(x==3)
{
sett[rt]=c;
mul[rt]=1;
add[rt]=0;
sum1[rt]=((r-l+1)*c)%mod;
sum2[rt]=((r-l+1)*(c*c)%mod)%mod;
sum3[rt]=((r-l+1)*(((c*c)%mod*c)%mod))%mod;
}
else if(x==2)
{
mul[rt]=(mul[rt]*c)%mod;
if(add[rt])
add[rt]=(add[rt]*c)%mod;
sum1[rt]=(sum1[rt]*c)%mod;
sum2[rt]=((sum2[rt]*c)%mod*c)%mod;
sum3[rt]=(((sum3[rt]*c)%mod*c)%mod*c)%mod;
}
else if(x==1)
{
add[rt]+=c;
ll tmp =(((c*c)%mod*c)%mod*(r-l+1))%mod; //(r - l + 1) * c^3
sum3[rt]=(sum3[rt]+tmp+3*c*((sum2[rt]+sum1[rt]*c)%mod))%mod;
sum2[rt]=(sum2[rt]+(c*c%mod*(r-l+1)%mod)+2*sum1[rt]*c)%mod;
sum1[rt]=(sum1[rt]+(r-l+1)*c)%mod;
}
return;
}
ll m=(l+r)>>1;
pushdown(rt,m-l+1,r-m);
if(L<=m) update(L,R,l,m,ls,c,x);
if(R>m) update(L,R,m+1,r,rs,c,x);
pushup(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt,ll c)
{
if(L<=l&&r<=R)
{
if(c==1)
return sum1[rt]%mod;
else if(c==2)
return sum2[rt]%mod;
else
return sum3[rt]%mod;
}
ll m=(l+r)>>1;
pushdown(rt,m-l+1,r-m);
ll ans=0;
if(L<=m) ans+=query(L,R,l,m,ls,c);
if(R>m) ans+=query(L,R,m+1,r,rs,c);
return ans%mod;
}
int main()
{
ll l,r,c,x,n,m;
while(~scanf("%lld%lld",&n,&m)&&n+m)
{
build(1,n,1);
while(m--)
{
scanf("%lld%lld%lld%lld",&x,&l,&r,&c);
if(x!=4)
update(l,r,1,n,1,c,x);
else
printf("%lld\n",query(l,r,1,n,1,c));
}
}
}