社区讨论
麻烦大佬帮忙看看,线段树套矩乘
学术版参与者 3已保存回复 5
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @mhjnz9t9
- 此快照首次捕获于
- 2025/11/04 05:40 4 个月前
- 此快照最后确认于
- 2025/11/04 05:40 4 个月前
题目在这里
代码有点长不过打有一些注释,出现的问题是MLE,如果数组开小就会RE,而且我猜测就算改好了空间也很可能会超时。请各位大佬帮忙看看,谢谢
CPP#include<bits/stdc++.h>
using namespace std;
#define N 1000010
#define mod 998244353
int n, m;
long long a[N][4];
struct matrix{
int a[4][4];
inline matrix(){
for(int i=0; i<=4; i++){
for(int j=0; j<=4; j++){
a[i][j] = 0;
}
}
}
matrix operator * (const matrix &T) const{
matrix res;
for(int i=0; i<4; i++){
res.a[i][0] = (((1ll*a[i][0]*T.a[0][0])%mod) + ((1ll*a[i][1]*T.a[1][0])%mod) + ((1ll*a[i][2]*T.a[2][0])%mod) + ((1ll*a[i][3]*T.a[3][0])%mod))%mod;
res.a[i][1] = (((1ll*a[i][0]*T.a[0][1])%mod) + ((1ll*a[i][1]*T.a[1][1])%mod) + ((1ll*a[i][2]*T.a[2][1])%mod) + ((1ll*a[i][3]*T.a[3][1])%mod))%mod;
res.a[i][2] = (((1ll*a[i][0]*T.a[0][2])%mod) + ((1ll*a[i][1]*T.a[1][2])%mod) + ((1ll*a[i][2]*T.a[2][2])%mod) + ((1ll*a[i][3]*T.a[3][2])%mod))%mod;
res.a[i][3] = (((1ll*a[i][0]*T.a[0][3])%mod) + ((1ll*a[i][1]*T.a[1][3])%mod) + ((1ll*a[i][2]*T.a[2][3])%mod) + ((1ll*a[i][3]*T.a[3][3])%mod))%mod;
}//因为听说这题会卡常,所以虽然可能用处不大但还是展开了内层循环,代码显得很丑了
return res;
}
};
matrix I, A, B, C, D, E, F;
struct Tree{
int l, r;
bool lazy;
matrix val, tag;
}t[N<<2];
inline void init(){//根据7种操作设计的不同矩阵
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(i==j) I.a[i][j]=1;
else I.a[i][j]=0;//I是最后用来计数的矩阵
}
}
A.a[0][0] = A.a[1][0] = A.a[1][1] = A.a[2][2] = A.a[3][3] = 1;//a[1][0]=1 A+B的
B.a[0][0] = B.a[1][1] = B.a[2][1] = B.a[2][2] = B.a[3][3] = 1;//同理这个是B+C
C.a[0][0] = C.a[0][2] = C.a[1][1] = C.a[2][2] = C.a[3][3] = 1;//C+A
D.a[0][0]=D.a[1][1]=D.a[2][2]=D.a[3][3]=1;//A+v
E.a[0][0]=E.a[2][2]=E.a[3][3]=1;//B*v
F.a[0][0]=F.a[1][1]=F.a[3][3]=1;//=v
for(int i=1; i<=n<<4; i++) t[i].tag=I;
}
inline void push_down(int p){
t[p<<1].val = t[p<<1].val*t[p].tag;
t[p<<1|1].val = t[p<<1|1].val*t[p].tag;
t[p<<1].tag = t[p<<1].tag*t[p].tag;
t[p<<1|1].tag = t[p<<1|1].tag*t[p].tag;
t[p<<1].lazy = t[p<<1|1].lazy = true;
t[p].lazy = false; t[p].tag = I;
return ;
}
inline void pushup(int p){//真正要维护的不过是一个1*4矩阵 [A, B, C, 当前节点表示多少水晶球]
t[p].val.a[0][0] = (t[p<<1].val.a[0][0] + t[p<<1|1].val.a[0][0]) % mod;
t[p].val.a[0][1] = (t[p<<1].val.a[0][1] + t[p<<1|1].val.a[0][1]) % mod;
t[p].val.a[0][2] = (t[p<<1].val.a[0][2] + t[p<<1|1].val.a[0][2]) % mod;
t[p].val.a[0][3] = (t[p<<1].val.a[0][3] + t[p<<1|1].val.a[0][3]);
return ;
}
void build(int p, int l, int r){
t[p].l = l, t[p].r = r;
if(l==r){
t[p].val.a[0][0] = a[l][1]%mod;
t[p].val.a[0][1] = a[l][2]%mod;
t[p].val.a[0][2] = a[l][3]%mod;
t[p].val.a[0][3] = 1;//叶子节点[A, B, C, 1]
return ;
}
int mid = l+r>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
return ;
}
void change(int p, int l, int r, matrix k){//修改
if(t[p].l >= l && t[p].r <= r){
t[p].val = t[p].val*k;
t[p].tag = t[p].tag*k;
t[p].lazy = true;
return ;
}
if(t[p].lazy) push_down(p);
int mid = t[p].l+t[p].r>>1;
if(l<=mid) change(p<<1, l, r, k);
if(r>mid) change(p<<1|1, l, r, k);
pushup(p);
return ;
}
matrix query(int p, int l, int r, matrix k){//查询
matrix c, c1, c2;
if(l<=t[p].l && r>=t[p].r) return t[p].val*k;
if(t[p].lazy) push_down(p);
int mid = t[p].l+t[p].r>>1;
if(l<=mid) c1 = query(p<<1, l, r, k);
if(r>mid) c2 = query(p<<1|1, l, r, k);
for(int i=0;i<4;i++)
c.a[0][i] = (c1.a[0][i]+c2.a[0][i])%mod;
return c;
}
int main()
{
freopen("P7453.in", "r", stdin);
freopen("P7453.out", "w", stdout);
init();
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%lld%lld%lld", &a[i][1], &a[i][2], &a[i][3]);
build(1, 1, n);
scanf("%d", &m);
while(m--){
int opt, l, r;
scanf("%d%d%d", &opt, &l, &r);
cin.clear();
if(opt==1) change(1, l, r, A);
if(opt==2) change(1, l, r, B);
if(opt==3) change(1, l, r, C);
if(opt==7) {
matrix ans = query(1, l, r, I);
printf("%d %d %d\n", ans.a[0][0]%mod, ans.a[0][1]%mod, ans.a[0][2]%mod);
}
if(opt>=4&&opt<=6){//第四到第六种操作要按需完善之前设计的矩阵
int v; scanf("%d", &v);
if(opt==4){
D.a[3][0] = v;
change(1, l, r, D);
}
if(opt==5){
E.a[1][1] = v;
change(1, l, r, E);
}
if(opt==6){
F.a[3][2] = v;
change(1, l, r, F);
}
}
}
return 0;
}
回复
共 5 条回复,欢迎继续交流。
正在加载回复...