P10061 [SNOI2024] 矩阵

原题链接

考虑记录每个元素相邻的四个元素,发现每次旋转只会影响最周围一圈的点与旁边一圈点的连接,所以考虑十字链表维护,单次操作 \(O(n)\) 可以接受。

矩阵加怎么做,我们还是采用上述的思路,在维护元素相邻的时候维护相邻两个元素的差值,这样可以 \(O(n)\) 矩阵加,因为还是只对最周围一圈操作。查询元素值是单次 \(O(n)\) 的,因为你要从链表最边缘开始走,但是查询 \(n\) 个连续的元素值是均摊 \(O(1)\) 的。

然后思考一下细节,发现每次旋转以后方向是会变的,要知道每次应该往哪个方向走应当知道当前元素旋转了几次,每次旋转都是对一个子矩阵,所以还是相当于矩阵加,多维护一个即可。总结是:

  • \(O(n)\) 求出最周围一圈与旁边一圈的元素值和旋转次数。
  • \(O(n)\) 将最周围一圈点的旋转次数都加一。
  • \(O(n)\) 修改十字链表,更新链表值,元素值差值和旋转次数差值。

但是代码很难写,值得一提的细节是在旋转时可以先存下来最周围一圈每个点和其相邻点还有两者的方向,这样应该要好写一点。还有就是将旋转次数加一时要不重不漏,需要注意角落和只有一条线或点的情况。

卡常的话,最开始不要快速幂,直接用 \((i,j-1)\) 的值乘 \(i+1\)。操作中不需要取模,只开几个 long long 比较快。大量的 %4 可以改成 &3,但这条可能有副作用。

我的代码没有封装,因为我觉得封装了更难调。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=3010;
int MOD=998244353,n,q;long long ans;
struct node{long long num,v[4];int sum,a[4],s[4];}p[MAXN*MAXN];
struct rota{int x,tx,y,ty;}K[4][MAXN];
inline int N(int x,int y)
{
    if(x>n||y>n) return 0;
    return x*(n+1)+y;
}
signed main()
{
    // freopen("matrix.in","r",stdin);
    // freopen("matrix.out","w",stdout);
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n>>q;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
        {
            int cur=N(i,j);
            p[cur].num=(j==1)?(i+1):p[cur-1].num*(i+1)%MOD;
            p[cur].a[0]=N(i,j+1);
            p[cur].a[1]=N(i+1,j);
            p[cur].a[2]=N(i,j-1);
            p[cur].a[3]=N(i-1,j);
        }
    for(int i=1;i<=n;++i) p[i].a[1]=N(1,i);
    for(int i=1;i<=n;++i) p[i*(n+1)].a[0]=N(i,1);
    for(int i=0;i<(n+1)*(n+1);++i)
        for(int j=0;j<4;++j)
            p[i].v[j]=p[p[i].a[j]].num-p[i].num;
    while(q--)
    {
        int opt,xa,ya,xb,yb,d;long long S=0;
        cin>>opt>>xa>>ya>>xb>>yb;
        if(opt==1)
        {
            S=0;
            for(int i=0,cur=xa*(n+1),c=0;i<=yb;++i)
            {
                int nxt=p[cur].a[c];
                if(i>=ya&&i<=yb)
                {
                    p[cur].num=S;p[cur].sum=c;
                    int x=cur,tx=(c+3)%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx]+1)%4;
                    p[y].num=S+p[x].v[tx],p[y].sum=(c+p[x].s[tx])%4;
                    K[0][i-ya]={x,tx,y,ty};
                }
                S=S+p[cur].v[c];
                c+=p[cur].s[c];c=(c+4)%4;cur=nxt;
            }
            S=0;
            for(int i=0,cur=xb*(n+1),c=0;i<=yb;++i)
            {
                int nxt=p[cur].a[c];
                if(i>=ya&&i<=yb)
                {
                    p[cur].num=S;p[cur].sum=c;
                    int x=cur,tx=(c+1)%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx]+3)%4;
                    p[y].num=S+p[x].v[tx],p[y].sum=(c+p[x].s[tx])%4;
                    K[1][i-ya]={x,tx,y,ty};
                }
                S=S+p[cur].v[c];
                c+=p[cur].s[c];c=(c+4)%4;cur=nxt;
            }
            S=0;
            for(int i=0,cur=ya,c=0;i<=xb;++i)
            {
                int nxt=p[cur].a[(c+1)%4];
                if(i>=xa&&i<=xb)
                {
                    p[cur].num=S;p[cur].sum=c;
                    int x=cur,tx=(c+2)%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx])%4;
                    p[y].num=S+p[x].v[tx],p[y].sum=(c+p[x].s[tx])%4;
                    K[2][i-xa]={x,tx,y,ty};
                }
                S=S+p[cur].v[(c+1)%4];
                c+=p[cur].s[(c+1)%4];c=(c+4)%4;cur=nxt;
            }
            S=0;
            for(int i=0,cur=yb,c=0;i<=xb;++i)
            {
                int nxt=p[cur].a[(c+1)%4];
                if(i>=xa&&i<=xb)
                {
                    p[cur].num=S;p[cur].sum=c;
                    int x=cur,tx=c%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx]+2)%4;
                    p[y].num=S+p[x].v[tx],p[y].sum=(c+p[x].s[tx])%4;
                    K[3][i-xa]={x,tx,y,ty};
                }
                S=S+p[cur].v[(c+1)%4];
                c+=p[cur].s[(c+1)%4];c=(c+4)%4;cur=nxt;
            }  
            for(int i=0;i<=xb-xa;++i) p[K[0][i].x].sum++;
            if(xa!=xb) for(int i=0;i<=xb-xa;++i) p[K[1][i].x].sum++;
            for(int i=1;i<xb-xa;++i) p[K[2][i].x].sum++;
            if(ya!=yb) for(int i=1;i<xb-xa;++i) p[K[3][i].x].sum++;
            for(int i=0;i<=xb-xa;++i)
            {
                int x=K[0][i].x,tx=K[0][i].tx;
                int y=K[2][xb-xa-i].y,ty=K[2][xb-xa-i].ty;
                p[x].a[tx]=y,p[y].a[ty]=x;
                p[x].v[tx]=p[y].num-p[x].num;
                p[y].v[ty]=p[x].num-p[y].num;
                p[x].s[tx]=(p[y].sum-p[x].sum+4)%4;
                p[y].s[ty]=(p[x].sum-p[y].sum+4)%4;
            }
            for(int i=0;i<=xb-xa;++i)
            {
                int x=K[1][i].x,tx=K[1][i].tx;
                int y=K[3][xb-xa-i].y,ty=K[3][xb-xa-i].ty;
                p[x].a[tx]=y,p[y].a[ty]=x;
                p[x].v[tx]=p[y].num-p[x].num;
                p[y].v[ty]=p[x].num-p[y].num;
                p[x].s[tx]=(p[y].sum-p[x].sum+4)%4;
                p[y].s[ty]=(p[x].sum-p[y].sum+4)%4;
            }
            for(int i=0;i<=xb-xa;++i)
            {
                int x=K[2][i].x,tx=K[2][i].tx;
                int y=K[1][i].y,ty=K[1][i].ty;
                p[x].a[tx]=y,p[y].a[ty]=x;
                p[x].v[tx]=p[y].num-p[x].num;
                p[y].v[ty]=p[x].num-p[y].num;
                p[x].s[tx]=(p[y].sum-p[x].sum+4)%4;
                p[y].s[ty]=(p[x].sum-p[y].sum+4)%4;
            }
            for(int i=0;i<=xb-xa;++i)
            {
                int x=K[3][i].x,tx=K[3][i].tx;
                int y=K[0][i].y,ty=K[0][i].ty;
                p[x].a[tx]=y,p[y].a[ty]=x;
                p[x].v[tx]=p[y].num-p[x].num;
                p[y].v[ty]=p[x].num-p[y].num;
                p[x].s[tx]=(p[y].sum-p[x].sum+4)%4;
                p[y].s[ty]=(p[x].sum-p[y].sum+4)%4;
            }
        }
        if(opt==2)
        {
            cin>>d;
            for(int i=0,cur=xa*(n+1),c=0;i<=yb;++i)
            {
                if(i>=ya&&i<=yb)
                {
                    int x=cur,tx=(c+3)%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx]+1)%4;
                    p[x].v[tx]-=d,p[y].v[ty]+=d;
                }
                int nxt=p[cur].a[c];c+=p[cur].s[c];c=(c+4)%4;cur=nxt;
            }
            for(int i=0,cur=xb*(n+1),c=0;i<=yb;++i)
            {
                if(i>=ya&&i<=yb)
                {
                    int x=cur,tx=(c+1)%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx]+3)%4;
                    p[x].v[tx]-=d,p[y].v[ty]+=d;
                }
                int nxt=p[cur].a[c];c+=p[cur].s[c];c=(c+4)%4;cur=nxt;
            }
            for(int i=0,cur=ya,c=0;i<=xb;++i)
            {
                if(i>=xa&&i<=xb)
                {
                    int x=cur,tx=(c+2)%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx])%4;
                    p[x].v[tx]-=d,p[y].v[ty]+=d;
                }
                int nxt=p[cur].a[(c+1)%4];c+=p[cur].s[(c+1)%4];c=(c+4)%4;cur=nxt;
            }
            for(int i=0,cur=yb,c=0;i<=xb;++i)
            {
                if(i>=xa&&i<=xb)
                {
                    int x=cur,tx=c%4;
                    int y=p[x].a[tx],ty=(c+p[x].s[tx]+2)%4;
                    p[x].v[tx]-=d,p[y].v[ty]+=d;
                }
                int nxt=p[cur].a[(c+1)%4];c+=p[cur].s[(c+1)%4];c=(c+4)%4;cur=nxt;
            }
        }
    }
    MOD=1e9+7;long long P=1;
    for(int i=1;i<=n;++i)
    {
        long long S=0;
        for(int j=i*(n+1),c=0;j;)
        {
            if(j%(n+1)) P=P*12345%MOD,ans=(ans+P*S)%MOD;
            int nxt=p[j].a[c];S=(S+p[j].v[c])%MOD;
            c+=p[j].s[c];c=(c+4)%4;j=nxt;
        }
    }
    cout<<(ans+MOD)%MOD<<'\n';return 0;
}
posted @ 2024-01-22 18:54  int_R  阅读(49)  评论(0编辑  收藏  举报