「THUSCH 2017」大魔法师
「THUSCH 2017」大魔法师
先考虑只有操作1,2,3的情况。
实际上每个数都可以用\(xA_i+yB_i+zC_i+K\)来表示。
那么对于操作4,只要\(K+=v\),操作5,只需\(x*=v,y*=v,z*=v,K*=v\),操作6,只需\(x=y=z=0,K=v\)。
直接使用分块来做,十分暴力。
每个块记录\(\sum A_i ,\sum B_i ,\sum C_i\)查询和重构块的时候展开表示形式即可。
#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r) {
static char c;
r=0;
while(c=getchar(),!isdigit(c));
do r=(r<<1)+(r<<3)+(c^48);
while(c=getchar(),isdigit(c));
}
bool cur1;
const int mn=250005;
const int mod=998244353;
int A[mn],B[mn],C[mn],n,m;
const int BLK=1600;
int blk;
struct nw{
int a,b,c,v;
void operator +=(const nw &A){
a=(a+A.a)%mod,b=(b+A.b)%mod;
c=(c+A.c)%mod,v=(v+A.v)%mod;
}
void operator *=(const int &vl){
a=1LL*a*vl%mod,b=1LL*b*vl%mod;
c=1LL*c*vl%mod,v=1LL*v*vl%mod;
}
}an[BLK][3];
int sum[BLK][3],mxd;
static inline void ad(int &a,int b){
mxd=a+b;
a=mxd<mod?mxd:mxd-mod;
}
void rebuild(int id){
int l=max(1,blk*id),r=min(n,blk*(id+1)-1);
int mid1,mid2,mid3;
sum[id][0]=0,sum[id][1]=0,sum[id][2]=0;
rep(q,l,r){
mid1=(1LL*an[id][0].a*A[q]+1LL*an[id][0].b*B[q]+1LL*an[id][0].c*C[q]+an[id][0].v)%mod;
mid2=(1LL*an[id][1].a*A[q]+1LL*an[id][1].b*B[q]+1LL*an[id][1].c*C[q]+an[id][1].v)%mod;
mid3=(1LL*an[id][2].a*A[q]+1LL*an[id][2].b*B[q]+1LL*an[id][2].c*C[q]+an[id][2].v)%mod;
A[q]=mid1,B[q]=mid2,C[q]=mid3;
ad(sum[id][0],mid1);
ad(sum[id][1],mid2);
ad(sum[id][2],mid3);
}
an[id][0]={1,0,0,0};
an[id][1]={0,1,0,0};
an[id][2]={0,0,1,0};
}
void operator_1(int l,int r){
int l_id=l/blk,r_id=r/blk;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)ad(A[q],B[q]),ad(sum[l_id][0],B[q]);
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)ad(A[q],B[q]),ad(sum[l_id][0],B[q]);
rep(q,r_id*blk,r)ad(A[q],B[q]),ad(sum[r_id][0],B[q]);
rep(q,l_id+1,r_id-1){
an[q][0]+=an[q][1];
ad(sum[q][0],sum[q][1]);
}
}
}
void operator_2(int l,int r){
int l_id=l/blk,r_id=r/blk;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)ad(B[q],C[q]),ad(sum[l_id][1],C[q]);
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)ad(B[q],C[q]),ad(sum[l_id][1],C[q]);
rep(q,r_id*blk,r)ad(B[q],C[q]),ad(sum[r_id][1],C[q]);
rep(q,l_id+1,r_id-1){
an[q][1]+=an[q][2];
ad(sum[q][1],sum[q][2]);
}
}
}
void operator_3(int l,int r){
int l_id=l/blk,r_id=r/blk;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)ad(C[q],A[q]),ad(sum[l_id][2],A[q]);
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)ad(C[q],A[q]),ad(sum[l_id][2],A[q]);
rep(q,r_id*blk,r)ad(C[q],A[q]),ad(sum[r_id][2],A[q]);
rep(q,l_id+1,r_id-1){
an[q][2]+=an[q][0];
ad(sum[q][2],sum[q][0]);
}
}
}
void operator_4(int l,int r,int vl){
int l_id=l/blk,r_id=r/blk;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)ad(A[q],vl);
sum[l_id][0]=(sum[l_id][0]+1LL*vl*(r-l+1))%mod;
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)ad(A[q],vl);
sum[l_id][0]=(sum[l_id][0]+1LL*vl*((l_id+1)*blk-l))%mod;
rep(q,r_id*blk,r)ad(A[q],vl);
sum[r_id][0]=(sum[r_id][0]+1LL*vl*(r-r_id*blk+1))%mod;
rep(q,l_id+1,r_id-1){
ad(an[q][0].v,vl);
sum[q][0]=(sum[q][0]+1LL*vl*blk)%mod;
}
}
}
void operator_5(int l,int r,int vl){
int l_id=l/blk,r_id=r/blk;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)sum[l_id][1]=(sum[l_id][1]+1LL*B[q]*(vl-1)+mod)%mod,B[q]=1LL*B[q]*vl%mod;
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)sum[l_id][1]=(sum[l_id][1]+1LL*B[q]*(vl-1)+mod)%mod,B[q]=1LL*B[q]*vl%mod;
rep(q,r_id*blk,r)sum[r_id][1]=(sum[r_id][1]+1LL*B[q]*(vl-1)+mod)%mod,B[q]=1LL*B[q]*vl%mod;
rep(q,l_id+1,r_id-1){
an[q][1]*=vl;
sum[q][1]=1LL*sum[q][1]*vl%mod;
}
}
}
void operator_6(int l,int r,int vl){
int l_id=l/blk,r_id=r/blk;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)sum[l_id][2]=(1LL*sum[l_id][2]+vl-C[q]+mod)%mod,C[q]=vl;
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)sum[l_id][2]=(1LL*sum[l_id][2]+vl-C[q]+mod)%mod,C[q]=vl;
rep(q,r_id*blk,r)sum[r_id][2]=(1LL*sum[r_id][2]+vl-C[q]+mod)%mod,C[q]=vl;
rep(q,l_id+1,r_id-1){
an[q][2].a=0,an[q][2].b=0,an[q][2].c=0,an[q][2].v=vl;
sum[q][2]=1LL*blk*vl%mod;
}
}
}
void query(int l,int r){
int l_id=l/blk,r_id=r/blk;
long long sm1=0,sm2=0,sm3=0;
if(l_id==r_id){
rebuild(l_id);
rep(q,l,r)sm1+=A[q],sm2+=B[q],sm3+=C[q];
}else{
rebuild(l_id),rebuild(r_id);
rep(q,l,(l_id+1)*blk-1)sm1+=A[q],sm2+=B[q],sm3+=C[q];
rep(q,r_id*blk,r)sm1+=A[q],sm2+=B[q],sm3+=C[q];
rep(q,l_id+1,r_id-1){
sm1+=sum[q][0];
sm2+=sum[q][1];
sm3+=sum[q][2];
}
}
sm1=(sm1%mod+mod)%mod,sm2=(sm2%mod+mod)%mod,sm3=(sm3%mod+mod)%mod;
printf("%d %d %d\n",(int)sm1,(int)sm2,(int)sm3);
}
bool cur2;
int main(){
// cerr<<(&cur1-&cur2)/1024.0/1024;
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
in(n);
rep(q,1,n)in(A[q]),in(B[q]),in(C[q]);
in(m);
blk=sqrt(n)/3+1;
for(int q=0;q<=n;q+=blk)an[q/blk][0]={1,0,0,0},an[q/blk][1]={0,1,0,0},an[q/blk][2]={0,0,1,0};
rep(q,1,n)ad(sum[q/blk][0],A[q]),ad(sum[q/blk][1],B[q]),ad(sum[q/blk][2],C[q]);
int ty,l,r,v;
rep(q,1,m){
in(ty),in(l),in(r);
if(ty==4||ty==5||ty==6)in(v);
if(ty==1)operator_1(l,r);
else if(ty==2)operator_2(l,r);
else if(ty==3)operator_3(l,r);
else if(ty==4)operator_4(l,r,v);
else if(ty==5)operator_5(l,r,v);
else if(ty==6)operator_6(l,r,v);
else query(l,r);
}
return 0;
}