写之前看到了大佬的文章,思路请移步大佬文章
链接Transformation HDU - 4578 多重懒标记 || 简洁暴力做法
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4578
多重懒标记暴力做法
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 100010;
const ll mod = 10007;
ll sum[maxn<<2][3],mul[maxn<<2],add[maxn<<2],cha[maxn<<2];
void Build(int l,int r,int rt)
{
sum[rt][0] = sum[rt][1] = sum[rt][2] = 0;
add[rt] = 0,mul[rt] = 1,cha[rt] = 0;
if(l == r){
return ;
}
int m = (l + r)>>1;
Build(l,m,rt<<1);
Build(m + 1,r,rt<<1|1);
}
void PushUp(int rt)
{
for(int i = 0; i < 3; i++){
sum[rt][i] = (sum[rt<<1][i] + sum[rt<<1|1][i]) % mod;
}
}
//更新加法
void Up1(int rt,int l,int r,ll val)
{
int len = r - l + 1;
//加法时次方和更新顺序必须是3->2->1;
sum[rt][2] = (sum[rt][2]+val*val%mod*val%mod*len%mod+3*val*sum[rt][1]%mod+3*val*val%mod*sum[rt][0]%mod) % mod;
sum[rt][1]=(sum[rt][1]+val*val%mod*len%mod+2*val*sum[rt][0]%mod) % mod;
sum[rt][0]=(sum[rt][0]+val*len) % mod;
}
//更新乘法
void Up2(int rt,ll val)
{
sum[rt][2] = sum[rt][2] * val % mod * val % mod * val % mod;
sum[rt][1] = sum[rt][1] * val % mod * val % mod;
sum[rt][0] = sum[rt][0] * val % mod;
}
//更新改值操作
void Up3(int rt,int l,int r,ll val)
{
int len = r - l + 1;
sum[rt][0] = val * len % mod;
sum[rt][1] = val * val % mod * len % mod;
sum[rt][2] = val * val % mod * val % mod * len % mod;
}
//优先级:更改值->乘法->加法
void PushDown(int l,int r,int rt)
{
int lr = rt<<1,rr = rt<<1|1;
int m = (l + r)>>1;
if(cha[rt]){
cha[lr] = cha[rr] = cha[rt];
mul[lr] = mul[rr] = 1;
add[lr] = add[rr] = 0;
ll val = cha[rt];
Up3(lr,l,m,val);
Up3(rr,m + 1,r,val);
cha[rt] = 0;
}
/*这里优先级乘法大于加法,因为如果先加后乘,如果目标指令是先乘再加
结果却变成了先加再乘,导致错误*/
if(mul[rt] != 1){
mul[lr] = mul[lr] * mul[rt] % mod;
mul[rr] = mul[rr] * mul[rt] % mod;
add[lr] = add[lr] * mul[rt] % mod;
add[rr] = add[rr] * mul[rt] % mod;
Up2(lr,mul[rt]);
Up2(rr,mul[rt]);
mul[rt] = 1;
}
if(add[rt]){
add[lr] = (add[lr] + add[rt]) % mod;
add[rr] = (add[rr] + add[rt]) % mod;
Up1(lr,l,m,add[rt]);
Up1(rr,m + 1,r,add[rt]);
add[rt] = 0;
}
}
void Update(int L,int R,int oper,ll val,int l,int r,int rt)
{
if(L <= l&&r <= R){
if(oper == 3){
Up3(rt,l,r,val);
mul[rt] = 1,add[rt] = 0,cha[rt] = val;
}
else if(oper == 2){
Up2(rt,val);
mul[rt] = mul[rt] * val % mod;
/*保证按照PushDown中的下推顺序
更新左右节点还是会按照规定的顺序进行运算*/
add[rt] = add[rt] * val % mod;
}
else{
Up1(rt,l,r,val);
add[rt] = (add[rt] + val) % mod;
}
return ;
}
PushDown(l,r,rt);
int m = (l + r)>>1;
if(L <= m){
Update(L,R,oper,val,l,m,rt<<1);
}
if(R > m){
Update(L,R,oper,val,m + 1,r,rt<<1|1);
}
PushUp(rt);
}
ll Query(int L,int R,int l,int r,int rt,int oper)
{
if(L <= l&&r<=R){
return sum[rt][oper] % mod;
}
PushDown(l,r,rt);
int m = (l + r)>>1;
ll ans = 0;
if(L <= m){
ans += Query(L,R,l,m,rt<<1,oper) % mod;
}
if(R > m){
ans += Query(L,R,m + 1,r,rt<<1|1,oper) % mod;
}
return ans % mod;
}
int main()
{
int m,n;
while(scanf("%d%d",&n,&m),n){
Build(1,n,1);
while(m--){
int oper,l,r;
ll val;
scanf("%d%d%d%lld",&oper,&l,&r,&val);
if(oper <= 3){
Update(l,r,oper,val,1,n,1);
}
else{
ll ans = Query(l,r,1,n,1,val - 1) % mod;
printf("%lld\n",ans);
}
}
}
return 0;
}
/*
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
*/