HDU4578 Transformation(线段树)
/**
有3种改变操作,需要3个lazy来记录;
每种操作之间有优先关系
change>mul>add;
传递时按优先关系进行
记录p= 1 2 3使得sum即可
注意取模
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#define lson l,mid,now<<1
#define rson mid+1,r,now<<1|1
#define ls now<<1
#define rs now<<1|1
#define all left,right,k
#define inf 0x3f3f3f3f
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e5+10;
const int mod=10007;
using namespace std;
ll tree[4*maxn][4],add[4*maxn],mul[4*maxn],ch[4*maxn];
/// 数 lazy加 lazy乘 lazy替换
void built(int l,int r,int now)
{
int mid=(l+r)>>1;
add[now]=ch[now]=0;
mul[now]=1;
tree[now][1]=tree[now][2]=tree[now][3]=0;
if(l==r) return ;
built(lson);
built(rson);
}
void pushup(int now)
{
for(int i=1;i<=3;i++)
tree[now][i]=(tree[ls][i]+tree[rs][i])%mod;
}
void pushdown(int l,int r,int now)
{
int mid=(l+r)>>1;
if(ch[now]!=0)///如果发生替换
{
///改变ls rs的值 直接计算即可
tree[ls][1]=(ch[now]*(mid-l+1))%mod;
tree[ls][2]=((ch[now]*ch[now])%mod*(mid-l+1))%mod;
tree[ls][3]=(((ch[now]*ch[now])%mod*ch[now])%mod)*(mid-l+1);
tree[rs][1]=(ch[now]*(r-mid))%mod;
tree[rs][2]=((ch[now]*ch[now])%mod*(r-mid))%mod;
tree[rs][3]=(((ch[now]*ch[now])%mod*ch[now])%mod)*(r-mid);
///将ch传递 ls rs之前未传递的+*清零
ch[ls]=ch[rs]=ch[now];
add[ls]=add[rs]=ch[now]=0;
mul[ls]=mul[rs]=1;
}
if(mul[now]!=1)///乘法
{
///mul 传递乘法分配
add[ls]=(add[ls]*mul[now])%mod;
add[rs]=(add[rs]*mul[now])%mod;
mul[ls]=(mul[ls]*mul[now])%mod;
mul[rs]=(mul[rs]*mul[now])%mod;
tree[ls][1]=(tree[ls][1]*mul[now])%mod;
tree[ls][2]=((tree[ls][2]*mul[now])%mod*mul[now])%mod;
tree[ls][3]=(((tree[ls][3]*mul[now])%mod*mul[now])%mod*mul[now])%mod;
tree[rs][1]=(tree[rs][1]*mul[now])%mod;
tree[rs][2]=((tree[rs][2]*mul[now])%mod*mul[now])%mod;
tree[rs][3]=(((tree[rs][3]*mul[now])%mod*mul[now])%mod*mul[now])%mod;
mul[now]=1;
}
if(add[now]!=0)///加法
{
add[ls]=(add[ls]+add[now])%mod;
add[rs]=(add[rs]+add[now])%mod;
///(a+b)^2=a^2+2ab+b^2;
///累加一下 得到(a1+b)^2+...+(an+b)^2=(a1^2+..+an^2)+2*(a1+..+an)*b+(1+...+n)b^2;
///同理可以得到(a+b)^3;
tree[ls][3]=(tree[ls][3]+(tree[ls][2]*add[now]*3)%mod+((add[now]*add[now])%mod*tree[ls][1]*3)%mod+((add[now]*add[now])%mod*add[now])%mod*(mid-l+1))%mod;
tree[ls][2]=(tree[ls][2]+(tree[ls][1]*add[now]*2)%mod+(add[now]*add[now])%mod*(mid-l+1))%mod;
tree[ls][1]=(tree[ls][1]+add[now]*(mid-l+1)%mod)%mod;
tree[rs][3]=(tree[rs][3]+(tree[rs][2]*add[now]*3)%mod+((add[now]*add[now])%mod*tree[rs][1]*3)%mod+((add[now]*add[now])%mod*add[now]%mod)*(r-mid))%mod;
tree[rs][2]=(tree[rs][2]+(tree[rs][1]*add[now]*2)%mod+(add[now]*add[now])%mod*(r-mid))%mod;
tree[rs][1]=(tree[rs][1]+add[now]*(r-mid)%mod)%mod;
add[now]=0;
}
}
void updata(int l,int r,int now,int left,int right,int k,int cmd)
{
int mid=(l+r)>>1,len=r-l+1;
if(left<=l&&r<=right)
{
if(cmd==1)
{
add[now]=(add[now]+k)%mod;
tree[now][3]=(tree[now][3]+((tree[now][2]*k)%mod*3)%mod+(((tree[now][1]*k)%mod*k)%mod*3)%mod+(((len*k)%mod*k)%mod*k)%mod)%mod;
///裂项展开相加
tree[now][2]=(tree[now][2]+((tree[now][1]*k)%mod*2)%mod+((len*k)%mod*k)%mod)%mod;
tree[now][1]=(tree[now][1]+(k*len)%mod)%mod;
}
if(cmd==2)
{
add[now]=(add[now]*k)%mod;
mul[now]=(mul[now]*k)%mod;
tree[now][1]=(tree[now][1]*k)%mod;
tree[now][2]=((tree[now][2]*k)%mod*k)%mod;
tree[now][3]=(((tree[now][3]*k)%mod*k)%mod*k)%mod;
}
if(cmd==3)
{
///如果是替换操作 将当前值改变
///还要将之前为传递的+*操作标记清掉
ch[now]=k%mod;
add[now]=0;
mul[now]=1;
tree[now][1]=(k*len)%mod;
tree[now][2]=((k*k)%mod*len)%mod;
tree[now][3]=(((k*k)%mod*k)%mod*len)%mod;
}
return ;
}
if(add[now]!=0||mul[now]!=1||ch[now]!=0)
pushdown(l,r,now);
if(left<=mid) updata(lson,all,cmd);
if(right>mid) updata(rson,all,cmd);
pushup(now);
}
int query(int l,int r,int now,int left,int right,int k)
{
int mid=(l+r)>>1;
if(left<=l&&r<=right)
{
return tree[now][k];
}
if(add[now]!=0||mul[now]!=1||ch[now]!=0)
pushdown(l,r,now);
int ans=0;
if(left<=mid) ans+=query(lson,all);
if(right>mid) ans+=query(rson,all);
return ans%mod;
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m))
{
if(n+m==0) break;
int cmd,l,r,k;
built(1,n,1);
while(m--)
{
scanf("%d%d%d%d",&cmd,&l,&r,&k);
if(cmd==4)
printf("%d\n",query(1,n,1,l,r,k));
else
updata(1,n,1,l,r,k,cmd);
}
}
return 0;
}