Time limit 8000 ms
Memory limit 65536 kB
OS Windows
Source 2013ACM-ICPC杭州赛区全国邀请赛
感想
线段树加法乘法大合集,有了这些操作,其他的区间平均值、区间方差什么的都不是事儿了。和这题相比,[AHOI2009]维护序列就太简单了,只有乘法加法区间和……
顺便,一开始不说p的大小,直到输入那里才说是想吓死人啊。
解题思路
和维护序列那题一样,依然从标记之间的关系来看,推一推公式,看一个操作对该区间的其他标记、总和、平方和、立方和的影响。
时间不早了,扔两个链接,去睡了敷衍
- https://blog.csdn.net/BOYxiejunBOY/article/details/53008894
- https://www.cnblogs.com/H-Vking/p/4297973.html
垃圾CSDN,开始封禁博客园链接了,急了吧,让你之前设计反人类,让你广告恶心人,活该用户变少
源代码
我这代码仿佛在打表
#include<stdio.h>
#include<string.h>
#include<algorithm>
const long long mod=10007;
int T;
int n,m;
struct Node{
int l,r;
long long lazyadd,lazymul,lazyset;
//0,1,-1.设置set标记时,马上清空add、mul。下放时,如果三个都有,说明是在set之后放的
long long sum[4];
}t[400010];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
void build(int x,int l,int r)
{
memset(&t[x],0,sizeof(t[x]));
t[x].l=l;
t[x].r=r;
t[x].lazymul=1;
t[x].lazyset=-1;
if(l==r) return;
int mid=l+r>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
}
inline void pushdown(int x)
{
if(~t[x].lazyset)
{
long long b=t[x].lazyset%mod;
t[x].lazyset=-1;
int len=t[ls(x)].r-t[ls(x)].l+1;
t[ls(x)].sum[1]=len*b%mod;
t[ls(x)].sum[2]=len*b%mod*b%mod;
t[ls(x)].sum[3]=len*b%mod*b*b%mod;
len=(t[rs(x)].r-t[rs(x)].l+1);
t[rs(x)].sum[1]=len*b%mod;
t[rs(x)].sum[2]=len*b%mod*b%mod;
t[rs(x)].sum[3]=len*b%mod*b*b%mod;
t[ls(x)].lazyset=t[rs(x)].lazyset=b;
t[ls(x)].lazyadd=t[rs(x)].lazyadd=0;
t[ls(x)].lazymul=t[rs(x)].lazymul=1;
}
if(t[x].lazymul!=1)
{
long long b = t[x].lazymul%mod;
t[x].lazymul = 1;
t[ls(x)].lazyadd*=b;t[ls(x)].lazyadd%=mod;
t[ls(x)].lazymul*=b;t[ls(x)].lazymul%=mod;
t[ls(x)].sum[1]*=b;
t[ls(x)].sum[2]*=b*b%mod;
t[ls(x)].sum[3]*=b*b%mod*b;
t[ls(x)].sum[1]%=mod;
t[ls(x)].sum[2]%=mod;
t[ls(x)].sum[3]%=mod;
t[rs(x)].lazyadd*=b;t[rs(x)].lazyadd%=mod;
t[rs(x)].lazymul*=b;t[rs(x)].lazymul%=mod;
t[rs(x)].sum[1]*=b;
t[rs(x)].sum[2]*=b*b%mod;
t[rs(x)].sum[3]*=b*b%mod*b;
t[rs(x)].sum[1]%=mod;
t[rs(x)].sum[2]%=mod;
t[rs(x)].sum[3]%=mod;
}
if(t[x].lazyadd)
{
long long b=t[x].lazyadd;//顺序321
t[x].lazyadd=0;
int len=t[ls(x)].r-t[ls(x)].l+1;
t[ls(x)].sum[3]+=len*b%mod*b*b%mod+t[ls(x)].sum[1]*b%mod*b*3%mod+t[ls(x)].sum[2]*b*3%mod;
t[ls(x)].sum[2]+=len*b%mod*b%mod+t[ls(x)].sum[1]*b*2%mod;
t[ls(x)].sum[1]+=len*b%mod;
t[ls(x)].sum[1]%=mod;
t[ls(x)].sum[2]%=mod;
t[ls(x)].sum[3]%=mod;
t[ls(x)].lazyadd+=b;t[ls(x)].lazyadd%=mod;
len=t[rs(x)].r-t[rs(x)].l+1;
t[rs(x)].sum[3]+=len*b%mod*b*b%mod+t[rs(x)].sum[1]*b%mod*b*3%mod+t[rs(x)].sum[2]*b*3%mod;
t[rs(x)].sum[2]+=len*b%mod*b%mod+t[rs(x)].sum[1]*b*2%mod;
t[rs(x)].sum[1]+=len*b%mod;
t[rs(x)].sum[1]%=mod;
t[rs(x)].sum[2]%=mod;
t[rs(x)].sum[3]%=mod;
t[rs(x)].lazyadd+=b;t[rs(x)].lazyadd%=mod;
}
}
inline void pushup(int x)
{
t[x].sum[1]=(t[ls(x)].sum[1]+t[rs(x)].sum[1])%mod;
t[x].sum[2]=(t[ls(x)].sum[2]+t[rs(x)].sum[2])%mod;
t[x].sum[3]=(t[ls(x)].sum[3]+t[rs(x)].sum[3])%mod;
}
void add(int x,int l,int r,long long k)
{
if(l<=t[x].l&&t[x].r<=r)
{
t[x].lazyadd+=k;
t[x].lazyadd%=mod;
int len=t[x].r-t[x].l+1;
t[x].sum[3]+=3*k*t[x].sum[2]%mod+3*k*k%mod*t[x].sum[1]%mod+len*k%mod*k*k%mod;
t[x].sum[2]+=2*k*t[x].sum[1]%mod+len*k%mod*k%mod;
t[x].sum[1]+=len*k%mod;
t[x].sum[1]%=mod;
t[x].sum[2]%=mod;
t[x].sum[3]%=mod;
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(l<=mid) add(ls(x),l,r,k);
if(r>mid) add(rs(x),l,r,k);
pushup(x);
}
void mult(int x,int l,int r,long long k)
{
if(l<=t[x].l&&t[x].r<=r)
{
t[x].lazymul*=k;
t[x].lazymul%=mod;
t[x].lazyadd*=k;//第一次交题的时候这步操作漏了,打乘法标记的时候记得把加法标记也乘一下
t[x].lazyadd%=mod;
t[x].sum[3]*=k*k%mod*k%mod;
t[x].sum[2]*=k*k%mod;
t[x].sum[1]*=k;
t[x].sum[1]%=mod;
t[x].sum[2]%=mod;
t[x].sum[3]%=mod;
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(l<=mid) mult(ls(x),l,r,k);
if(r>mid) mult(rs(x),l,r,k);
pushup(x);
}
void change(int x,int l,int r,long long k)
{
if(l<=t[x].l&&t[x].r<=r)
{
int len=t[x].r-t[x].l+1;
t[x].lazyset=k,t[x].lazyadd=0,t[x].lazymul=1;
t[x].sum[3]=len*k%mod*k*k%mod;
t[x].sum[2]=len*k%mod*k%mod;
t[x].sum[1]=len*k%mod;
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(l<=mid) change(ls(x),l,r,k);
if(r>mid) change(rs(x),l,r,k);
pushup(x);
}
long long que(int x,int l,int r,long long p)
{
if(l<=t[x].l&&t[x].r<=r)
{
return t[x].sum[p];
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
long long ans=0;
if(l<=mid) ans+=que(ls(x),l,r,p);
if(r>mid) ans+=que(rs(x),l,r,p);
return ans%mod;
}
int main()
{
while((scanf("%d%d",&n,&m),n||m))
{
build(1,1,n);
int opt,a,b;
long long c;
while(m--)
{
scanf("%d%d%d%I64d",&opt,&a,&b,&c);//这题是Windows系统
if(opt==1)
add(1,a,b,c);
else if(opt==2)
mult(1,a,b,c);
else if(opt==3)
change(1,a,b,c);
else if(opt==4)
printf("%I64d\n",que(1,a,b,c));
}
}
return 0;
}