题目链接:hdu 4578
思路:这道题目有个关键点,就是三个操作的优先级,优先级如下:1改变>2乘>3加,可以这么理解,先定义三个lazy0,lazy1,lazy2的意义,分别表示将要加的数,将要乘上的数,将要变成的数c,那么一旦你执行操作1(改变),那么lazy2=c, lazy1要置为1,lazy0要置于0,同样,你一旦操作2乘c,那么你lazy1=lazy1*c,lazy0=lazy0*c。 最后,你如果操作3加,那么你只要将lazy0=lazy0 + c. 所以可以看出优先级是改变>乘>加。 因此pushdown的时候,因先对优先级高的先操作,因为它会影响后面的操作。
代码:
#include<cstdio>
#define ll long long
const int mod = 10007;
const int maxn = 1e5+5;
#define mid (L + R)/2
#define ls rt*2
#define rs rt*2+1
#define lson ls,L,mid
#define rson rs,mid+1,R
ll sum[maxn<<2], sum1[maxn<<2], sum2[maxn<<2];
ll lazy0[maxn<<2], lazy1[maxn<<2], lazy2[maxn<<2];//加,乘,变
void build(int rt, int L, int R)
{
lazy0[rt]=lazy2[rt]=sum[rt]=sum1[rt]=sum2[rt]= 0;
lazy1[rt] = 1;
if(L == R) return ;
build(lson);
build(rson);
}
void pushDown(int rt, int L, int R)
{
if(lazy2[rt]){//变
sum2[ls] = 1ll*(((lazy2[rt]*lazy2[rt])%mod*lazy2[rt])%mod*(mid-L+1))%mod;
sum2[rs] = 1ll*(((lazy2[rt]*lazy2[rt])%mod*lazy2[rt])%mod*(R-mid))%mod;
sum1[ls] = 1ll*((lazy2[rt]*lazy2[rt])%mod*(mid-L+1))%mod;
sum1[rs] = 1ll*((lazy2[rt]*lazy2[rt])%mod*(R-mid))%mod;
sum[ls] = 1ll*lazy2[rt]*(mid-L+1)%mod;
sum[rs] = 1ll*lazy2[rt]*(R-mid)%mod;
lazy2[ls] = lazy2[rs] = lazy2[rt];
lazy1[ls] = lazy1[rs] = 1;
lazy0[ls] = lazy0[rs] = 0;
lazy2[rt] = 0;
}
if(lazy1[rt] != 1){//乘
sum2[ls] = 1ll*((sum2[ls]*lazy1[rt])%mod*(lazy1[rt]*lazy1[rt])%mod)%mod;
sum2[rs] = 1ll*((sum2[rs]*lazy1[rt])%mod*(lazy1[rt]*lazy1[rt])%mod)%mod;
sum1[ls] = 1ll*(sum1[ls]*lazy1[rt])%mod*lazy1[rt]%mod;
sum1[rs] = 1ll*(sum1[rs]*lazy1[rt])%mod*lazy1[rt]%mod;
sum[ls] = 1ll*sum[ls]*lazy1[rt]%mod;
sum[rs] = 1ll*sum[rs]*lazy1[rt]%mod;
lazy1[ls] = 1ll*lazy1[ls]*lazy1[rt]%mod;
lazy1[rs] = 1ll*lazy1[rs]*lazy1[rt]%mod;
if(lazy0[ls])
lazy0[ls] = 1ll*lazy0[ls]*lazy1[rt]%mod;
if(lazy0[rs])
lazy0[rs] = 1ll*lazy0[rs]*lazy1[rt]%mod;
lazy1[rt] = 1;
}
if(lazy0[rt]){//加 sum2[rt] + 1ll*(R-L+1)*val*val*val + 3ll*val*(sum[rt]*val + 1ll*sum1[rt]);
sum2[ls] = sum2[ls] + 1ll*((mid-L+1)*(lazy0[rt]*lazy0[rt])%mod*lazy0[rt])%mod + 3ll*(lazy0[rt]*((sum[ls]*lazy0[rt])%mod + 1ll*sum1[ls])%mod)%mod;
sum2[ls] %= mod;
sum2[rs] = sum2[rs] + 1ll*((R-mid)*(lazy0[rt]*lazy0[rt])%mod*lazy0[rt])%mod + 3ll*lazy0[rt]*(sum[rs]*lazy0[rt] + 1ll*sum1[rs]);
sum2[rs] %= mod;
sum1[ls] = sum1[ls] + 1ll*lazy0[rt]*lazy0[rt]*(mid-L+1) + 2ll*sum[ls]*lazy0[rt];
sum1[ls] %= mod;
sum1[rs] = sum1[rs] + 1ll*lazy0[rt]*lazy0[rt]*(R-mid) + 2ll*sum[rs]*lazy0[rt];
sum1[rs] %= mod;
sum[ls] = sum[ls] + 1ll*lazy0[rt]*(mid-L+1);
sum[ls] %= mod;
sum[rs] = sum[rs] + 1ll*lazy0[rt]*(R-mid);
sum[rt] %= mod;
lazy0[ls] += lazy0[rt];
lazy0[ls] %= mod;
lazy0[rs] += lazy0[rt];
lazy0[rs] %= mod;
lazy0[rt] = 0;
}
}
void upDate(int rt, int L, int R, int l, int r, ll val, int op)
{
if(l <= L && R <= r){//加
if(op == 1){
sum2[rt] = sum2[rt] + 1ll*(R-L+1)*((val*val)%mod*val)%mod + 3ll*val*(((sum[rt]*val)%mod + 1ll*sum1[rt]))%mod;
sum2[rt] %= mod;
sum1[rt] = sum1[rt]+1ll*(R-L+1)*(val*val)%mod+2ll*(val*sum[rt])%mod;
sum1[rt] %= mod;
sum[rt] = sum[rt] + 1ll*val*(R - L + 1);
sum[rt] %= mod;
lazy0[rt] += val;
lazy0[rt] %= mod;
}
else if(op == 2){//乘
sum2[rt] = 1ll*sum2[rt]*((val*val)%mod*val)%mod;
sum1[rt] = 1ll*(sum1[rt] * (val*val)%mod)%mod;
sum[rt] = 1ll*val*sum[rt]%mod;
if(lazy0[rt])
lazy0[rt] = 1ll*lazy0[rt]*val%mod;
lazy1[rt] = 1ll*lazy1[rt]*val%mod;
}
else if(op == 3){//变
sum2[rt] = 1ll*((val*val)%mod*val*(R-L+1))%mod;
sum1[rt] = 1ll*val*val*(R-L+1)%mod;
sum[rt] = 1ll*val*(R - L + 1)%mod;
lazy0[rt] = 0;
lazy1[rt] = 1;
lazy2[rt] = val;
}
return ;
}
pushDown(rt, L, R);
if(l <= mid) upDate(lson, l, r, val, op);
if(r > mid) upDate(rson, l, r, val, op);
sum[rt] = sum[ls] + sum[rs];
sum1[rt] = sum1[ls] + sum1[rs];
sum2[rt] = sum2[ls] + sum2[rs];
sum[rt] %= mod;
sum1[rt] %= mod;
sum2[rt] %= mod;
}
ll query(int rt, int L, int R, int l, int r, int op)
{
if(l <= L && R <= r){
if(op == 1){
return sum[rt];
}
else if(op == 2){
return sum1[rt];
}
else if(op == 3){
return sum2[rt];
}
}
ll res = 0ll;
pushDown(rt,L,R);
if(l <= mid) res += query(lson,l,r,op);
if(r > mid) res += query(rson,l,r,op);
return res%mod;
}
int main()
{
ll n, m;
ll a, b, c, d;
while(~scanf("%lld%lld", &n, &m)){
if(n==0 && m== 0)break;
build(1, 1, n);
for(int i = 0; i < m; i++){
scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
if(a == 1){
upDate(1,1,n,b,c,d,1);
}
else if(a == 2){
upDate(1,1,n,b,c,d,2);
}
else if(a == 3){
upDate(1,1,n,b,c,d,3);
}
else if(a == 4){
ll ans = query(1,1,n,b,c,d);
printf("%lld\n", ans);
}
}
}
return 0;
}