CodeChef SEPT17 简要题解

写完QGRID之后心力憔悴,根本不想动CHALLENGE。

CHEFSUM

签到。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

inline void Sol()
{
    int n = Read(), p = 0, r = 1 << 30;
    for (int i = 1, x; i <= n; i ++)
        if ((x = Read()) < r)
            r = x, p = i;
    printf("%d\n", p);
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

MINPERM

签到。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

inline void Sol()
{
    int n = Read();
    if (n & 1)
    {
        for (int i = 1; i <= n - 3; i ++)
            printf("%d ", (i - 1 ^ 1) + 1);
        printf("%d %d %d\n", n - 1, n, n - 2);
    }
    else
    {
        for (int i = 1; i <= n - 2; i ++)
            printf("%d ", (i - 1 ^ 1) + 1);
        printf("%d %d\n", n, n - 1);
    }
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

CHEFPDIG

签到。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 100005;

int cnt[10];
char s[MAXN];

inline void Sol()
{
    mset(cnt, 0);
    scanf("%s", s + 1);
    for (int i = 1; s[i]; i ++)
        cnt[s[i] - '0'] ++;
    for (int i = 65; i <= 90; i ++)
    {
        if ((i / 10 ^ i % 10))
        {
           if (cnt[i / 10] && cnt[i % 10])
            putchar(i);
        }
        else if (cnt[i / 10] >= 2)
            putchar(i);
    }
    putchar(10);
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

SEACO

倒着做。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 100005;
const int mod = 1e9 + 7;

int n, m, typ[MAXN], l[MAXN], r[MAXN], a[MAXN], b[MAXN];

inline void Sol()
{
    n = Read(), m = Read();
    for (int i = 1; i <= m; i ++)
        typ[i] = Read(), l[i] = Read(), r[i] = Read(), b[i] = 0;
    for (int i = 1; i <= n; i ++)
        a[i] = 0;
    b[m + 1] = 1;
    for (int i = m; i; i --)
    {
        b[i] = (b[i] + b[i + 1]) % mod;
        if (typ[i] == 1)
            a[l[i]] = (a[l[i]] + b[i]) % mod, a[r[i] + 1] = (a[r[i] + 1] - b[i] + mod) % mod;
        else
            b[r[i]] = (b[r[i]] + b[i]) % mod, b[l[i] - 1] = (b[l[i] - 1] - b[i] + mod) % mod;
    }
    for (int i = 1; i <= n; i ++)
        printf("%d%c", a[i] = (a[i] + a[i - 1]) % mod, i == n ? '\n' : ' ');
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

FILLMTR

0 的缩起来,1的连边,判二分图。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 100005;
const int MAXM = 1000005;

int n, m, u[MAXM], v[MAXM], w[MAXM], f[MAXN], c[MAXN];
vector <int> adj[MAXN];

inline int Find(int x)
{
    while (x ^ f[x])
        x = f[x] = f[f[x]];
    return x;
}

inline bool Dfs(int x)
{
    for (auto y : adj[x])
        if (!~c[y])
        {
            c[y] = c[x] ^ 1;
            if (!Dfs(y))
                return false;
        }
        else if (c[y] == c[x])
            return false;
    return true;
}

inline void Sol()
{
    n = Read(), m = Read();
    for (int i = 1; i <= n; i ++)
        f[i] = i, c[i] = -1, adj[i].clear();
    for (int i = 1; i <= m; i ++)
        u[i] = Read(), v[i] = Read(), w[i] = Read();
    for (int i = 1; i <= m; i ++)
        if (!w[i])
            f[Find(u[i])] = Find(v[i]);
    for (int i = 1; i <= m; i ++)
        if (w[i])
        {
            if (Find(u[i]) == Find(v[i]))
                return (void)puts("no");
            adj[Find(u[i])].pb(Find(v[i]));
            adj[Find(v[i])].pb(Find(u[i]));
        }
    for (int i = 1; i <= n; i ++)
        if (!~c[i])
        {
            c[i] = 0;
            if (!Dfs(i))
                return (void)puts("no");
        }
    puts("yes");
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

WEASELTX

先把深度相同的缩起来,然后处理出 f(i,j) 表示 i 次操作后深度为j的是否有影响,注意到 f(i,j)=f(i1,j)xorf(i,j1) ,然后分块。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline LL Read()
{
    LL x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 262150;

int n, Q;
vector <int> adj[MAXN];
LL a[MAXN], b[MAXN], c[MAXN], d[515][515];

inline void Dfs(int x, int d, int p)
{
    if (d)
        b[d] ^= a[x];
    for (auto y : adj[x])
        if (y ^ p)
            Dfs(y, d + 1, x);
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    n = Read(), Q = Read();
    for (int i = 1, x, y; i < n; i ++)
        x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x);
    for (int i = 0; i < n; i ++)
        a[i] = Read();
    Dfs(0, 0, -1);
    for (int i = 0; i < 262144; i ++)
        for (int j = ((i & 511) ^ 511), k = j; ; k = (k - 1 & j))
        {
            d[i >> 9][k] ^= b[i];
            if (!k)
                break;
        }
    for (int i = 0; i < 262144; i ++)
        for (int j = (i >> 9 ^ 511), k = j; ; k = (k - 1 & j))
        {
            c[i] ^= d[k][i & 511];
            if (!k)
                break;
        }
    while (Q --)
    {
        LL x = Read();
        if (!x)
            printf("%lld\n", a[0]);
        else
            printf("%lld\n", a[0] ^ c[x - 1 & 262143]);
    }
    return 0;
}

SUMCUBE

管道取珠,难点在三元环计数, mm 做就好了。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 100005;
const int mod = 1e9 + 7;

namespace CircleCount
{
    int e_cnt, ans, hed[MAXN], p[MAXN], v[MAXN], d[MAXN];
    bool vis[MAXN];

    inline bool Cmp(int x, int y)
    {
        return d[x] < d[y] || (d[x] == d[y] && x < y);
    }

    inline void Addedge(int x, int y)
    {
        p[++ e_cnt] = y; v[e_cnt] = hed[x]; hed[x] = e_cnt;
    }

    inline int Sol(int n, int m, int *x, int *y)
    {
        e_cnt = ans = 0;
        for (int i = 1; i <= n; i ++)
            hed[i] = d[i] = 0;
        for (int i = 1; i <= m; i ++)
            d[x[i]] ++, d[y[i]] ++;
        for (int i = 1; i <= m; i ++)
            if (Cmp(x[i], y[i]))
                Addedge(x[i], y[i]);
            else
                Addedge(y[i], x[i]);
        for (int x = 1; x <= n; x ++)
            for (int i = hed[x]; i; i = v[i])
            {
                int y = p[i];
                for (int j = hed[x]; j; j = v[j])
                    vis[p[j]] = 1;
                for (int j = hed[y]; j; j = v[j])
                    ans += vis[p[j]];
                for (int j = hed[x]; j; j = v[j])
                    vis[p[j]] = 0;
            }
        return 6LL * ans % mod;
    }
}

int n, m, k, pw[MAXN], x[MAXN], y[MAXN], d[MAXN];

inline void Solve1()
{
    printf("%d\n", 1LL * m * pw[n - 2] % mod);
}

inline void Solve2()
{
    int ret = 0, w1 = m, w2 = 0, w3 = 1LL * m * m % mod;
    for (int i = 1; i <= n; i ++)
        d[i] = 0;
    for (int i = 1; i <= m; i ++)
        d[x[i]] ++, d[y[i]] ++;
    for (int i = 1; i <= n; i ++)
        w2 = (1LL * d[i] * (d[i] - 1) + w2) % mod;
    w3 = (1LL * w3 - w2 - w1 + mod + mod) % mod;
    ret = (1LL * w1 * pw[n - 2] + ret) % mod;
    if (n >= 3)
        ret = (1LL * w2 * pw[n - 3] + ret) % mod;
    if (n >= 4)
        ret = (1LL * w3 * pw[n - 4] + ret) % mod;
    printf("%d\n", ret);
}

inline void Solve3()
{
    int ret = 0, w1 = m, w2 = 0, w3 = 1LL * m * m % mod, w4 = 0, w5 = 0, w6 = CircleCount::Sol(n, m, x, y), w7 = 0, w8 = 1LL * m * m * m % mod;
    for (int i = 1; i <= n; i ++)
        d[i] = 0;
    for (int i = 1; i <= m; i ++)
        d[x[i]] ++, d[y[i]] ++;
    for (int i = 1; i <= n; i ++)
        w2 = (1LL * d[i] * (d[i] - 1) + w2) % mod, w4 = (1LL * d[i] * (d[i] - 1) * (d[i] - 2) + w4) % mod;
    w3 = (1LL * w3 - w2 - w1 + mod + mod) % mod;
    w2 = 3LL * w2 % mod;
    w3 = 3LL * w3 % mod;
    for (int i = 1; i <= m; i ++)
        w5 = (1LL * (d[x[i]] - 1) * (d[y[i]] - 1) + w5) % mod;
    w5 = (6LL * w5 - 3LL * w6 % mod + mod) % mod;
    for (int i = 1; i <= n; i ++)
        w7 = (3LL * d[i] * (d[i] - 1) * (m - d[i]) + w7) % mod;
    w7 = ((1LL * w7 - 3LL * w6 - 2LL * w5) % mod + mod) % mod;
    w8 = ((1LL * w8 - w1 - w2 - w3 - w4 - w5 - w6 - w7) % mod + mod) % mod;
    cerr << w1 << " " << w2 << " " << w3 << " " << w4 << " " << w5 << " " << w6 << " " << w7 << " " << w8 << endl;
    ret = (1LL * w1 * pw[n - 2] + ret) % mod;
    if (n >= 3)
        ret = (1LL * w2 * pw[n - 3] + ret) % mod;
    if (n >= 4)
        ret = (1LL * w3 * pw[n - 4] + ret) % mod;
    if (n >= 4)
        ret = (1LL * w4 * pw[n - 4] + ret) % mod;
    if (n >= 4)
        ret = (1LL * w5 * pw[n - 4] + ret) % mod;
    if (n >= 3)
        ret = (1LL * w6 * pw[n - 3] + ret) % mod;
    if (n >= 5)
        ret = (1LL * w7 * pw[n - 5] + ret) % mod;
    if (n >= 6)
        ret = (1LL * w8 * pw[n - 6] + ret) % mod;
    printf("%d\n", ret);
}

inline void Sol()
{
    n = Read(), m = Read(), k = Read();
    for (int i = 1; i <= m; i ++)
        x[i] = Read(), y[i] = Read();
    if (k == 1)
        return Solve1();
    if (k == 2)
        return Solve2();
    return Solve3();
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    pw[0] = 1;
    for (int i = 1; i <= 100000; i ++)
        pw[i] = (pw[i - 1] << 1) % mod;
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

WEASELSC

DP,在单调栈上三分。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
    int x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 100005;
const int MAXM = 55;

int n, m, tp, a[MAXN], st[MAXN];
LL f[MAXM][MAXN], ans;

inline void Dp(int k)
{
    tp = 0;
    for (int i = 1; i <= n; i ++)
    {
        while (tp && a[st[tp]] >= a[i])
            tp --;
        st[++ tp] = i;
        int l = 0, r = tp - 1;
        while (r - l > 4)
        {
            int m1 = l + (r - l) / 3, m2 = r - (r - l) / 3;
            LL r1 = f[k - 1][st[m1]] + 1LL * a[st[m1 + 1]] * (i - st[m1]), r2 = f[k - 1][st[m2]] + 1LL * a[st[m2 + 1]] * (i - st[m2]);
            if (r1 < r2)
                l = m1;
            else
                r = m2;
        }
        for (int j = l; j <= r; j ++)
            f[k][i] = max(f[k][i], f[k - 1][st[j]] + 1LL * a[st[j + 1]] * (i - st[j]));
        ans = max(ans, f[k][i]);
    }
}

inline void Sol()
{
    n = Read(), m = Read() + 1, ans = 0;
    for (int i = 1; i <= n; i ++)
        a[i] = Read();
    mset(f, 0);
    for (int i = 1; i <= m; i ++)
        Dp(i);
    reverse(a + 1, a + n + 1);
    mset(f, 0);
    for (int i = 1; i <= m; i ++)
        Dp(i);
    printf("%lld\n", ans);
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    for (int T = Read(); T; T --)
        Sol();
    return 0;
}

QGRID

这是个毒瘤题。
线段树维护一个区间的 2m 个端点两两之间最短路。
然后暴力。
这是个毒瘤题。

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <LL, LL> pLL;
typedef pair <int, int> pii;

template <typename T> inline bool Chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }

inline LL Read()
{
    LL x = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (;  isdigit(c); c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

const int MAXN = 400005;

int n, m, Q, rel[MAXN], idx[MAXN], pos[MAXN];
LL dow[3][MAXN], rig[3][MAXN], val[3][MAXN];

struct Node
{
    int l, r;
    LL dis[6][6], tag[6][6];
    pLL pre[6][6];

    friend Node operator + (const Node &a, const Node &b)
    {
        Node c;
        LL dis[9][9];
        pLL pre[9][9];
        mset(dis, 127 / 7);
        for (int i = 0; i < m * 2; i ++)
            for (int j = 0; j < m * 2; j ++)
                if (Chkmin(dis[i][j], a.dis[i][j]))
                    pre[i][j] = mp(1LL << i * m * 2 + j, 0);
        for (int i = 0; i < m * 2; i ++)
            for (int j = 0; j < m * 2; j ++)
                if (Chkmin(dis[i + m][j + m], b.dis[i][j]))
                    pre[i + m][j + m] = mp(0, 1LL << i * m * 2 + j);
        for (int k = 0; k < m * 3; k ++)
            for (int i = 0; i < m * 3; i ++)
                for (int j = 0; j < m * 3; j ++)
                    if (Chkmin(dis[i][j], dis[i][k] + dis[k][j]))
                        pre[i][j] = mp(pre[i][k].xx | pre[k][j].xx, pre[i][k].yy | pre[k][j].yy);
        for (int i = 0; i < m * 2; i ++)
            for (int j = 0; j < m * 2; j ++)
                c.dis[i][j] = dis[i < m ? i : i + m][j < m ? j : j + m], c.pre[i][j] = pre[i < m ? i : i + m][j < m ? j : j + m], c.tag[i][j] = 0;
        c.l = a.l, c.r = b.r;
        return c;
    }
} e[MAXN];

inline Node Init(int p)
{
    Node c;
    LL dis[6][6], pre[6][6];
    mset(dis, 127 / 7);
    for (int i = 0; i < m; i ++)
        dis[i][i + m] = dis[i + m][i] = rig[i][p], pre[i][i + m] = pre[i + m][i] = 1LL << i;
    for (int i = 0; i + 1 < m; i ++)
        dis[i][i + 1] = dis[i + 1][i] = dow[i][p], pre[i][i + 1] = pre[i + 1][i] = 1LL << i + m;
    for (int i = 0; i + 1 < m; i ++)
        dis[i + m][i + m + 1] = dis[i + m + 1][i + m] = dow[i][p + 1], pre[i + m][i + m + 1] = pre[i + m + 1][i + m] = 1LL << i + m * 2;
    for (int k = 0; k < m * 2; k ++)
        for (int i = 0; i < m * 2; i ++)
            for (int j = 0; j < m * 2; j ++)
                if (Chkmin(dis[i][j], dis[i][k] + dis[k][j]))
                    pre[i][j] = pre[i][k] | pre[k][j];
    for (int i = 0; i < m * 2; i ++)
        for (int j = 0; j < m * 2; j ++)
            c.dis[i][j] = dis[i][j], c.pre[i][j] = mp(pre[i][j], 0), c.tag[i][j] = 0;
    c.l = c.r = p;
    return c;
}

inline void Build(int x, int l, int r)
{
    if (l == r)
        return (void)(e[x] = Init(l), idx[x] = l, pos[l] = x);
    int mid = l + r >> 1;
    Build(x << 1, l, mid); Build(x << 1 | 1, mid + 1, r);
    e[x] = e[x << 1] + e[x << 1 | 1];
}

inline void Pushdown(Node &x, Node &a, Node &b)
{
    for (int i = 0; i < m * 2; i ++)
        for (int j = 0; j < m * 2; j ++)
            if (x.tag[i][j])
            {
                LL l = x.pre[i][j].xx, r = x.pre[i][j].yy;
                while (l)
                {
                    int tmp = rel[(l & -l) % MAXN];
                    a.tag[tmp / (m * 2)][tmp % (m * 2)] += x.tag[i][j];
                    l -= l & -l;
                }
                while (r)
                {
                    int tmp = rel[(r & -r) % MAXN];
                    b.tag[tmp / (m * 2)][tmp % (m * 2)] += x.tag[i][j];
                    r -= r & -r;
                }
                x.tag[i][j] = 0;
            }
}

inline void Pushdown(int x)
{
    if (e[x].l ^ e[x].r)
        return Pushdown(e[x], e[x << 1], e[x << 1 | 1]);
    int p = idx[x];
    for (int i = 0; i < m * 2; i ++)
        for (int j = 0; j < m * 2; j ++)
            if (i ^ j)
                if (e[x].tag[i][j])
                {
                    for (int k = 0; k < m; k ++)
                        if (e[x].pre[i][j].xx >> k & 1)
                            val[k][p] += e[x].tag[i][j], val[k][p + 1] += e[x].tag[i][j];
                    for (int k = 0; k < m - 1; k ++)
                        if (e[x].pre[i][j].xx >> k + m & 1)
                            val[k][p] += e[x].tag[i][j], val[k + 1][p] += e[x].tag[i][j];
                    for (int k = 0; k < m - 1; k ++)
                        if (e[x].pre[i][j].xx >> k + m * 2 & 1)
                            val[k][p + 1] += e[x].tag[i][j], val[k + 1][p + 1] += e[x].tag[i][j];
                    e[x].tag[i][j] = 0;
                }
}

struct Info
{
    int st[MAXN], tp;
    Node sum[MAXN];

    inline void Query(int x, int l, int r, int ql, int qr)
    {
        ::Pushdown(x);
        if (l == ql && r == qr)
            return (void)(st[++ tp] = x);
        int mid = l + r >> 1;
        if (qr <= mid)
            return Query(x << 1, l, mid, ql, qr);
        if (ql > mid)
            return Query(x << 1 | 1, mid + 1, r, ql, qr);
        return Query(x << 1, l, mid, ql, mid), Query(x << 1 | 1, mid + 1, r, mid + 1, qr);
    }

    inline Node Get(int l, int r)
    {
        tp = 0;
        if (l > r)
        {
            Node tmp;
            mset(tmp.dis, 127 / 7);
            return tmp;
        }
        Query(1, 0, n, l, r);
        sum[1] = e[st[1]];
        for (int i = 2; i <= tp; i ++)
            sum[i] = sum[i - 1] + e[st[i]];
        return sum[tp];
    }

    inline void Pushdown()
    {
        if (!tp)
            return ;
        for (int i = tp; i > 1; i --)
            ::Pushdown(sum[i], sum[i - 1], e[st[i]]);
        e[st[1]] = sum[1];
    }
} way[3];

inline void Modify()
{
    int x1 = Read() - 1, y1 = Read(), x2 = Read() - 1, y2 = Read(), t1 = m * m * 4, t2 = t1 + m * m;
    LL v = Read(), dis[6][6], pre[6][6];
    mset(dis, 127 / 7);
    val[x1][y1] += v; val[x2][y2] += v;
    if (x1 == x2 && y1 == y2)
        return ;
    if (y1 > y2)
        swap(x1, x2), swap(y1, y2);
    Node a = way[0].Get(0, y1 - 1), b = way[1].Get(y1, y2 - 1), c = way[2].Get(y2, n);
    if (y1 == y2)
        for (int i = 0; i < m; i ++)
            b.dis[i][i + m] = b.dis[i + m][i] = 0;
    for (int i = 0; i < m * 2; i ++)
        for (int j = 0; j < m * 2; j ++)
            dis[i][j] = b.dis[i][j], pre[i][j] = 1LL << i * m * 2 + j;
    for (int i = 0; i < m; i ++)
        for (int j = 0; j < m; j ++)
            if (Chkmin(dis[i][j], a.dis[i + m][j + m]))
                pre[i][j] = 1LL << t1 + i * m + j;
    for (int i = 0; i < m; i ++)
        for (int j = 0; j < m; j ++)
            if (Chkmin(dis[i + m][j + m], c.dis[i][j]))
                pre[i + m][j + m] = 1LL << t2 + i * m + j;
    for (int k = 0; k < m * 2; k ++)
        for (int i = 0; i < m * 2; i ++)
            for (int j = 0; j < m * 2; j ++)
                if (Chkmin(dis[i][j], dis[i][k] + dis[k][j]))
                    pre[i][j] = pre[i][k] | pre[k][j];
    LL tmp = pre[x1][x2 + m];
    for (int i = 0; i < m * 2; i ++)
        for (int j = 0; j < m * 2; j ++)
            if (tmp >> i * m * 2 + j & 1)
                way[1].sum[way[1].tp].tag[i][j] += v;
    for (int i = 0; i < m; i ++)
        for (int j = 0; j < m; j ++)
            if (tmp >> t1 + i * m + j & 1)
                way[0].sum[way[0].tp].tag[i + m][j + m] += v;
    for (int i = 0; i < m; i ++)
        for (int j = 0; j < m; j ++)
            if (tmp >> t2 + i * m + j & 1)
                way[2].sum[way[2].tp].tag[i][j] += v;
    for (int i = 0; i < 3; i ++)
        way[i].Pushdown();
}

inline void Query()
{
    static int st[MAXN];
    int x = Read() - 1, y = Read(), tp = 0;
    for (int i = pos[y - 1]; i; i >>= 1)
        st[++ tp] = i;
    while (tp)
        Pushdown(st[tp --]);
    for (int i = pos[y]; i; i >>= 1)
        st[++ tp] = i;
    while (tp)
        Pushdown(st[tp --]);
    printf("%lld\n", val[x][y] / 2);
}

int main()
{
#ifdef wxh010910
    freopen("data.in", "r", stdin);
#endif
    mset(dow, 127 / 7);
    mset(rig, 127 / 7);
    for (int i = 0; i < 60; i ++)
        rel[(1LL << i) % MAXN] = i;
    m = Read(), n = Read(), Q = Read();
    for (int i = 0; i < m - 1; i ++)
        for (int j = 1; j <= n; j ++)
            dow[i][j] = Read();
    for (int i = 0; i < m; i ++)
        for (int j = 1; j < n; j ++)
            rig[i][j] = Read();
    Build(1, 0, n);
    while (Q --)
        if (Read() == 1)
            Modify();
        else
            Query();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值