题目链接: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; }