P10061 [SNOI2024] 矩阵 题解

给矩阵中每个点一个编号,维护 $v_{i,0/1/2/3},w_{i,0/1/2/3}$ 表示 $i$ 点四周的点,$i$ 点四周的点与 $i$ 点的点权差。

一次操作只会改变选定的子矩形边框上 $O(n)$ 个点四周的点,分别修改它们的 $v,w$ 即可。

然而存在一个问题:旋转操作会使选定的子矩形内的点四周的点的方向发生变化,比如一个点上方的点转完之后会到它左方,

这会使找到一个子矩形边框上的点变得困难,考虑维护出每个点的朝向。

具体地,维护 $z_i$ 表示原来在 $i$ 上方的点现在在 $i$ 的哪个方向(也就是 $i$ 点转了几次),

于是一次旋转操作会使 $z$ 子矩形加一,找子矩形边框上的点时根据 $z$ 判断该往哪边走即可。

考虑如何维护 $z$。类似加法操作,维护 $d_{i,0/1/2/3}$ 表示 $i$ 四周的点与 $i$ 点的 $z$ 之差即可。

这样理论上就可以过了。如果需要在某些跑得飞慢的 OJ 上通过,可以参照下面的代码卡常:

#include <cstdio>
#define M 1000000007
struct S
{
    int v;
    long long w;
    int d;
} v[10000050][4];
int n, q, a[3050][3050], f[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
void U(int &p, int &z, long long &q, int o)
{
    int dz = v[p][(o + 4 - z) & 3].d;
    long long dq = v[p][(o + 4 - z) & 3].w;
    p = v[p][(o + 4 - z) & 3].v, z += dz, q += dq, z = (z & 3 + 4) & 3;
}
int Q(int x, int y, int &z, long long &q)
{
    int p = 0;
    z = 0;
    q = 0;
    while (x--)
        U(p, z, q, 2);
    while (y--)
        U(p, z, q, 3);
    return p;
}
signed main()
{
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; ++i)
    {
        long long z = 1;
        for (int j = 1; j <= n; ++j)
            z = z * (i + 1) % 998244353, a[i][j] = z;
    }
    for (int i = 0; i <= n + 1; ++i)
        for (int j = 0; j <= n + 1; ++j)
        {
            int u = i * (n + 2) + j;
            for (int k = 0, x, y; k < 4; ++k)
            {
                x = i + f[k][0], y = j + f[k][1];
                if (x < 0 || x > n + 1 || y < 0 || y > n + 1)
                    continue;
                v[u][k].v = x * (n + 2) + y, v[u][k].w = a[x][y] - a[i][j];
            }
        }
    for (int i = 0, o, u1, v1, u2, v2, k, _, x, y, zx, zy; i < q; ++i)
    {
        scanf("%d%d%d%d%d", &o, &u1, &v1, &u2, &v2);
        k = u2 - u1 + 1;
        long long vx, vy;
        if (o & 1)
        {
            x = Q(u2, v1 - 1, zx, vx), y = Q(u1, v1, zy, vy);
            for (int j = 1; j <= k; ++j)
            {
                v[y][(4 - zy) & 3].v = x;
                v[y][(4 - zy) & 3].w = vx - vy;
                v[y][(4 - zy) & 3].d = zx - zy - 1;
                v[x][(7 - zx) & 3].v = y;
                v[x][(7 - zx) & 3].w = vy - vx;
                v[x][(7 - zx) & 3].d = zy - zx + 1;
                U(x, zx, vx, 0);
                if (j != k)
                    U(y, zy, vy, 3);
            }
            U(x, zx, vx, 3);
            for (int j = 1; j <= k; ++j)
            {
                v[y][(7 - zy) & 3].v = x;
                v[y][(7 - zy) & 3].w = vx - vy;
                v[y][(7 - zy) & 3].d = zx - zy - 1;
                v[x][(6 - zx) & 3].v = y;
                v[x][(6 - zx) & 3].w = vy - vx;
                v[x][(6 - zx) & 3].d = zy - zx + 1;
                U(x, zx, vx, 3);
                if (j != k)
                    U(y, zy, vy, 2);
            }
            U(x, zx, vx, 2);
            for (int j = 1; j <= k; ++j)
            {
                v[y][(6 - zy) & 3].v = x;
                v[y][(6 - zy) & 3].w = vx - vy;
                v[y][(6 - zy) & 3].d = zx - zy - 1;
                v[x][(5 - zx) & 3].v = y;
                v[x][(5 - zx) & 3].w = vy - vx;
                v[x][(5 - zx) & 3].d = zy - zx + 1;
                U(x, zx, vx, 2);
                if (j != k)
                    U(y, zy, vy, 1);
            }
            U(x, zx, vx, 1);
            for (int j = 1; j <= k; ++j)
            {
                v[y][(5 - zy) & 3].v = x;
                v[y][(5 - zy) & 3].w = vx - vy;
                v[y][(5 - zy) & 3].d = zx - zy - 1;
                v[x][(4 - zx) & 3].v = y;
                v[x][(4 - zx) & 3].w = vy - vx;
                v[x][(4 - zx) & 3].d = zy - zx + 1;
                U(x, zx, vx, 1);
                if (j != k)
                    U(y, zy, vy, 0);
            }
        }
        else
        {
            scanf("%d", &_);
            x = Q(u1 - 1, v1, zx, vx), y = Q(u1, v1, zy, vy);
            for (int j = 1; j <= v2 - v1 + 1; ++j)
            {
                v[y][(4 - zy) & 3].w = vx - vy - _;
                v[x][(6 - zx) & 3].w = vy - vx + _;
                U(x, zx, vx, 3);
                if (j != v2 - v1 + 1)
                    U(y, zy, vy, 3);
            }
            U(x, zx, vx, 2);
            for (int j = 1; j <= u2 - u1 + 1; ++j)
            {
                v[y][(7 - zy) & 3].w = vx - vy - _;
                v[x][(5 - zx) & 3].w = vy - vx + _;
                U(x, zx, vx, 2);
                if (j != u2 - u1 + 1)
                    U(y, zy, vy, 2);
            }
            U(x, zx, vx, 1);
            for (int j = 1; j <= v2 - v1 + 1; ++j)
            {
                v[y][(6 - zy) & 3].w = vx - vy - _;
                v[x][(4 - zx) & 3].w = vy - vx + _;
                U(x, zx, vx, 1);
                if (j != v2 - v1 + 1)
                    U(y, zy, vy, 1);
            }
            U(x, zx, vx, 0);
            for (int j = 1; j <= u2 - u1 + 1; ++j)
            {
                v[y][(5 - zy) & 3].w = vx - vy - _;
                v[x][(7 - zx) & 3].w = vy - vx + _;
                U(x, zx, vx, 0);
                if (j != u2 - u1 + 1)
                    U(y, zy, vy, 0);
            }
        }
    }
    int x = 0, zx = 0;
    long long _ = 1, vx = 0, s = 0;
    for (int i = 1; i <= n; ++i)
    {
        U(x, zx, vx, 2);
        int y = x, zy = zx;
        long long vy = vx;
        for (int j = 1; j <= n; ++j)
            U(y, zy, vy, 3), _ = _ * 12345 % M, s = (s + vy % M * _ % M) % M;
    }
    printf("%lld", s);
    return 0;
}
posted @ 2024-01-22 20:43  5k_sync_closer  阅读(7)  评论(0编辑  收藏  举报  来源