题意
样例最多10组,每组给你一个长度为n(n<=1e5)的数组,初始为0,
以下m(m<=1e5)次操作,操作分4种
1 x y c 区间+c
2 x y c 区间*c
3 x y c 区间赋值为c
前三种操作,保证c<=10000
4 x y c(1<=c<=3) 询问区间c次方和模10007的值
思路来源
校赛
题解
维护区间立方和、平方和、和,由于立方和就要维护这三个值,实际相当于就询问一个立方和
根据立方和公式、平方和公式推导出标记需要加的部分,
注意优先级 区间赋值>区间乘>区间加
区间赋值时,将区间赋值标记值v,区间乘标记置1,区间加标记置0
区间乘时,将区间乘标记*=v,区间加标记*=v
区间加时,仅将区间加标记+=v即可
实际并不复杂,然而很考验代码熟练度吧,写错一处查了好久QAQ
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10,M=10007;
int pf[M+5],lf[M+5];
int n,m,op,x,y,v;
struct node
{
int l,r;
int add,mul,cov,a[3];//加 乘 赋值 区间1-3次方和
}e[5*N];
void ADD(int &x,int y)
{
x+=y;
if(x>=M)x-=M;
if(x<0)x+=M;
}
void MUL(int &x,int y)
{
x*=y;
x%=M;
}
void pushup(int p)
{
for(int i=0;i<3;++i)
e[p].a[i]=(e[p<<1].a[i]+e[p<<1|1].a[i])%M;
}
void pushdown(int p)
{
int l=e[p<<1].r-e[p<<1].l+1,r=e[p<<1|1].r-e[p<<1|1].l+1;
if(e[p].cov)
{
int v=e[p].cov;
e[p<<1].cov=e[p<<1|1].cov=v;
e[p<<1].mul=e[p<<1|1].mul=1;
e[p<<1].add=e[p<<1|1].add=0;
e[p<<1].a[2]=1ll*l*lf[v]%M,e[p<<1|1].a[2]=1ll*r*lf[v]%M;
e[p<<1].a[1]=1ll*l*pf[v]%M,e[p<<1|1].a[1]=1ll*r*pf[v]%M;
e[p<<1].a[0]=1ll*l*v%M,e[p<<1|1].a[0]=1ll*r*v%M;
e[p].cov=0;
}
if(e[p].mul!=1)
{
int v=e[p].mul;
MUL(e[p<<1].mul,v),MUL(e[p<<1|1].mul,v);
MUL(e[p<<1].add,v),MUL(e[p<<1|1].add,v);
MUL(e[p<<1].a[2],lf[v]),MUL(e[p<<1|1].a[2],lf[v]);
MUL(e[p<<1].a[1],pf[v]),MUL(e[p<<1|1].a[1],pf[v]);
MUL(e[p<<1].a[0],v),MUL(e[p<<1|1].a[0],v);
e[p].mul=1;
}
if(e[p].add)
{
int v=e[p].add;
ADD(e[p<<1].add,v);
ADD(e[p<<1|1].add,v);
ADD(e[p<<1].a[2],(3ll*v*e[p<<1].a[1]+3ll*pf[v]*e[p<<1].a[0]+1ll*l*lf[v])%M);
ADD(e[p<<1|1].a[2],(3ll*v*e[p<<1|1].a[1]+3ll*pf[v]*e[p<<1|1].a[0]+1ll*r*lf[v])%M);
ADD(e[p<<1].a[1],(2ll*v*e[p<<1].a[0]+1ll*l*pf[v])%M);
ADD(e[p<<1|1].a[1],(2ll*v*e[p<<1|1].a[0]+1ll*r*pf[v])%M);
ADD(e[p<<1].a[0],1ll*l*v%M);
ADD(e[p<<1|1].a[0],1ll*r*v%M);
e[p].add=0;
}
}
void build(int p,int l,int r)
{
e[p].l=l;e[p].r=r;
for(int i=0;i<3;++i)e[p].a[i]=0;
e[p].cov=0;e[p].mul=1;e[p].add=0;
if(l==r)return;
int mid=(l+r)/2;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void add(int p,int ql,int qr,int v)
{
if(ql<=e[p].l&&e[p].r<=qr)
{
int l=e[p].r-e[p].l+1;
ADD(e[p].a[2],(3ll*v*e[p].a[1]+3ll*pf[v]*e[p].a[0]+1ll*l*lf[v])%M);
ADD(e[p].a[1],(2ll*v*e[p].a[0]+1ll*l*pf[v])%M);
ADD(e[p].a[0],1ll*l*v%M);
ADD(e[p].add,v);
return;
}
pushdown(p);
int mid=(e[p].l+e[p].r)/2;
if(ql<=mid)add(p<<1,ql,qr,v);
if(qr>mid)add(p<<1|1,ql,qr,v);
pushup(p);
}
void mul(int p,int ql,int qr,int v)
{
if(ql<=e[p].l&&e[p].r<=qr)
{
int l=e[p].r-e[p].l+1;
MUL(e[p].mul,v);
MUL(e[p].add,v);
MUL(e[p].a[2],lf[v]);
MUL(e[p].a[1],pf[v]);
MUL(e[p].a[0],v);
return;
}
pushdown(p);
int mid=(e[p].l+e[p].r)/2;
if(ql<=mid)mul(p<<1,ql,qr,v);
if(qr>mid)mul(p<<1|1,ql,qr,v);
pushup(p);
}
void cov(int p,int ql,int qr,int v)
{
if(ql<=e[p].l&&e[p].r<=qr)
{
int l=e[p].r-e[p].l+1;
e[p].cov=v;e[p].mul=1;e[p].add=0;
e[p].a[2]=1ll*l*lf[v]%M,
e[p].a[1]=1ll*l*pf[v]%M,
e[p].a[0]=1ll*l*v%M;
return;
}
pushdown(p);
int mid=(e[p].l+e[p].r)/2;
if(ql<=mid)cov(p<<1,ql,qr,v);
if(qr>mid)cov(p<<1|1,ql,qr,v);
pushup(p);
}
int ask(int p,int ql,int qr,int op)
{
if(ql<=e[p].l&&e[p].r<=qr)return e[p].a[op];
pushdown(p);
int mid=(e[p].l+e[p].r)/2,ans=0;
if(ql<=mid)ADD(ans,ask(p<<1,ql,qr,op));
if(qr>mid)ADD(ans,ask(p<<1|1,ql,qr,op));
return ans;
}
int main()
{
for(int i=1;i<M;++i)
{
pf[i]=(i*i)%M;
lf[i]=(pf[i]*i)%M;
}
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m)break;
build(1,1,n);
while(m--)
{
scanf("%d%d%d%d",&op,&x,&y,&v);
if(op==1)add(1,x,y,v);
else if(op==2)mul(1,x,y,v);
else if(op==3)cov(1,x,y,v);
else printf("%d\n",ask(1,x,y,v-1));
}
}
return 0;
}