三个数组分别是lazadd lazmul lazc 记录加数,乘数,和设定的数,lazc1 表示一次方之和lazc2 lazc3 以此类推,其中最要注意的就是乘操作和加操作顺序不同答案是不同的,所以假如设定乘法为先,那么下推函数就要把乘法标记下推放在加法前面,而且更新函数里面,如果在更新乘法的时候碰到此处标记有加法标记存在,先把加数乘了,在更新子树,就可以保证既是顺序不一样答案是一样的,就比如a=c+d,当乘f,可变乘af=cf+df,还有下推函数传入长度的时候傻逼了,居然取模了,取完mod导致区间长度错误,无法计算正确答案,找了一个晚上才找到的,还要感谢大佬的博客。
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <time.h>
#include <set>
#include <list>
#include <iostream>
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))
#define INF 0x3f3f3f3f
using namespace std;
const ll mod=1e4+7;
const int maxn=1e5+50;
ll lazc1[maxn<<2],lazc2[maxn<<2],lazc3[maxn<<2],lazadd[maxn<<2],lazc[maxn<<2],lazmul[maxn<<2];
void Push_up(int rt)
{
lazc1[rt]=(lazc1[rt<<1]%mod+lazc1[rt<<1|1]%mod)%mod;
lazc2[rt]=(lazc2[rt<<1]%mod+lazc2[rt<<1|1]%mod)%mod;
lazc3[rt]=(lazc3[rt<<1]%mod+lazc3[rt<<1|1]%mod)%mod;
}
void Push_down(int rt,ll m)
{
if(lazc[rt]!=0){
lazc1[rt<<1]=lazc[rt]*(m-(m>>1))%mod;
lazc1[rt<<1|1]=lazc[rt]*(m>>1)%mod;
lazc2[rt<<1]=lazc1[rt<<1]*lazc[rt]%mod;
lazc2[rt<<1|1]=lazc1[rt<<1|1]*lazc[rt]%mod;
lazc3[rt<<1]=lazc2[rt<<1]*lazc[rt]%mod;
lazc3[rt<<1|1]=lazc2[rt<<1|1]*lazc[rt]%mod;
lazadd[rt<<1]=0;
lazadd[rt<<1|1]=0;
lazmul[rt<<1]=1;
lazmul[rt<<1|1]=1;
lazc[rt<<1]=lazc[rt]%mod;
lazc[rt<<1|1]=lazc[rt]%mod;
lazc[rt]=0;
}
if(lazmul[rt]!=1){
if(lazadd[rt<<1])lazadd[rt<<1]=lazadd[rt<<1]*lazmul[rt]%mod;
if(lazadd[rt<<1|1])lazadd[rt<<1|1]=lazadd[rt<<1|1]*lazmul[rt]%mod;
lazmul[rt<<1]=lazmul[rt<<1]*lazmul[rt]%mod;
lazmul[rt<<1|1]=lazmul[rt<<1|1]*lazmul[rt]%mod;
lazc1[rt<<1]=lazc1[rt<<1]*lazmul[rt]%mod;
lazc2[rt<<1]=lazc2[rt<<1]*lazmul[rt]%mod*lazmul[rt]%mod;
lazc3[rt<<1]=lazc3[rt<<1]*lazmul[rt]%mod*lazmul[rt]%mod*lazmul[rt]%mod;
lazc1[rt<<1|1]=lazc1[rt<<1|1]*lazmul[rt]%mod;
lazc2[rt<<1|1]=lazc2[rt<<1|1]*lazmul[rt]%mod*lazmul[rt]%mod;
lazc3[rt<<1|1]=lazc3[rt<<1|1]*lazmul[rt]%mod*lazmul[rt]%mod*lazmul[rt]%mod;
lazmul[rt]=1;
}
if(lazadd[rt]!=0){
ll cl=lazadd[rt],cr=lazadd[rt];
ll cl3=cl*cl%mod*cl%mod,cr3=cr*cr%mod*cr%mod;
ll cl2=cl*cl%mod,cr2=cr*cr%mod;
ll ml=(m-(m>>1)),mr=(m>>1);
lazc3[rt<<1]=(lazc3[rt<<1]+3*cl2%mod*lazc1[rt<<1]%mod+3*cl%mod*lazc2[rt<<1]%mod+ml*cl3%mod)%mod;
lazc3[rt<<1|1]=(lazc3[rt<<1|1]+3*cr2%mod*lazc1[rt<<1|1]%mod+3*cr%mod*lazc2[rt<<1|1]%mod+mr*cr3%mod)%mod;
lazc2[rt<<1]=(lazc2[rt<<1]+2*cl%mod*lazc1[rt<<1]+ml*cl2%mod)%mod;
lazc2[rt<<1|1]=(lazc2[rt<<1|1]+2*cr%mod*lazc1[rt<<1|1]+mr*cr2%mod)%mod;
lazc1[rt<<1]=(lazc1[rt<<1]+ml*cl%mod)%mod;
lazc1[rt<<1|1]=(lazc1[rt<<1|1]+mr*cr%mod)%mod;
lazadd[rt<<1]=(lazadd[rt]%mod+lazadd[rt<<1]%mod)%mod;
lazadd[rt<<1|1]=(lazadd[rt]%mod+lazadd[rt<<1|1]%mod)%mod;
lazadd[rt]=0;
}
}
void Update(int L,int R,int l,int r,int rt,ll c,int ml)
{
if(L<=l && r<=R)
{
ll all=(r-l+1)%mod;
if(ml==1){
ll c3=c*c%mod*c%mod;
lazadd[rt]=(lazadd[rt]+c%mod)%mod;
lazc3[rt]=(lazc3[rt]+3*c%mod*c%mod*lazc1[rt]%mod+3*c%mod*lazc2[rt]%mod+all*c3%mod)%mod;
lazc2[rt]=(lazc2[rt]+2*c%mod*lazc1[rt]+all*c%mod*c%mod)%mod;
lazc1[rt]=(lazc1[rt]+c%mod*(r-l+1)%mod)%mod;
}
if(ml==2){
if(lazadd[rt])lazadd[rt]=lazadd[rt]*c%mod;
lazmul[rt]=lazmul[rt]*c%mod;
lazc1[rt]=lazc1[rt]*c%mod;
lazc2[rt]=lazc2[rt]*c%mod*c%mod;
lazc3[rt]=lazc3[rt]*c%mod*c%mod*c%mod;
}
if(ml==3){
lazc[rt]=c%mod;
lazadd[rt]=0;
lazmul[rt]=1;
lazc1[rt]=c%mod*all%mod;
lazc2[rt]=c%mod*lazc1[rt]%mod;
lazc3[rt]=c%mod*lazc2[rt]%mod;
}
return;
}
Push_down(rt,(r-l+1));
int mid=(l+r)>>1;
if(L<=mid)Update(L,R,l,mid,rt<<1,c,ml);
if(R>mid)Update(L,R,mid+1,r,rt<<1|1,c,ml);
Push_up(rt);
}
ll Query(int L,int R,int l,int r,int rt,int ml)
{
if(L<=l && r<=R)
{
if(ml==1)return lazc1[rt];
if(ml==2)return lazc2[rt];
if(ml==3)return lazc3[rt];
}
Push_down(rt,(r-l+1)%mod);
ll ANS=0;
int mid=(l+r)>>1;
if(L<=mid)ANS=(ANS+Query(L,R,l,mid,rt<<1,ml))%mod;
if(R>mid)ANS=(ANS+Query(L,R,mid+1,r,rt<<1|1,ml))%mod;
return ANS;
}
void mulclear(int l,int r,int rt)
{
lazmul[rt]=1;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
mulclear(l,mid,rt<<1);
mulclear(mid+1,r,rt<<1|1);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m) && n!=0 && m!=0){
memset(lazc,0,sizeof lazc);
memset(lazc1,0,sizeof lazc1);
memset(lazc2,0,sizeof lazc2);
memset(lazc3,0,sizeof lazc3);
memset(lazadd,0,sizeof lazadd);
mulclear(1,n,1);
for(int i=0;i<m;i++){
int ml,u,v,c;
scanf("%d%d%d%d",&ml,&u,&v,&c);
if(ml==4){
cout<<Query(u,v,1,n,1,c)<<endl;
}
else{
Update(u,v,1,n,1,(ll)c,ml);
}
}
}
return 0;
}