社区讨论

麻烦大佬帮忙看看,线段树套矩乘

学术版参与者 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 条回复,欢迎继续交流。

正在加载回复...