BZOJ 2738. 矩阵乘法

 

整体二分加上一个二维树状数组数点即可。

#include <bits/stdc++.h>

namespace IO {
    char buf[1 << 21], *p1 = buf, *p2 = buf;
    int p, p3 = -1;
    void read() {}
    inline int getc() {
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
    }
    template <typename T, typename... T2>
    inline void read(T &x, T2 &... oth) {
        T f = 1; x = 0;
        char ch = getc();
        while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getc(); }
        while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getc(); }
        x *= f;
        read(oth...);
    }
}

const int N = 507;
const int M = 500 * 500 + 6e4 + 7;
int w[M], n, Q;

struct Bit {
    int tree[N][N];
    inline int lowbit(int x) { return x & -x; }
    inline void add(int x, int y, int v) {
        for (int i = x; i <= n; i += lowbit(i))
            for (int j = y; j <= n; j += lowbit(j))
                tree[i][j] += v;
    }
    inline int query(int x, int y) {
        int ans = 0;
        for (int i = x; i; i -= lowbit(i))
            for (int j = y; j; j -= lowbit(j))
                ans += tree[i][j];
        return ans;
    }
    inline int query(int x1, int yy1, int x2, int y2) {
        return query(x2, y2) + query(x1 - 1, yy1 - 1) - query(x2, yy1 - 1) - query(x1 - 1, y2);
    }
} bit;

struct Node {
    int x1, yy1, x2, y2, k, id;
} q[M], q1[M], q2[M];
int ans[M];

void solve(int l, int r, int L, int R) {
    if (l > r || L > R) return;
    if (l == r) {
        for (int i = L; i <= R; i++)
            if (q[i].id) 
                ans[q[i].id] = w[l];
        return;
    }
    int mid = l + r >> 1;
    int cnt1 = 0, cnt2 = 0;
    for (int i = L; i <= R; i++) {
        if (q[i].id) {
            int sum = bit.query(q[i].x1, q[i].yy1, q[i].x2, q[i].y2);
            if (q[i].k > sum) q[i].k -= sum, q2[++cnt2] = q[i];
            else q1[++cnt1] = q[i];
        } else {
            if (q[i].k <= w[mid]) bit.add(q[i].x1, q[i].yy1, 1), q1[++cnt1] = q[i];
            else q2[++cnt2] = q[i];
        }
    }
    for (int i = 1; i <= cnt1; i++)
        if (!q1[i].id)
            bit.add(q1[i].x1, q1[i].yy1, -1);
    for (int i = 1; i <= cnt1; i++)
        q[L + i - 1] = q1[i];
    for (int i = 1; i <= cnt2; i++)
        q[L + cnt1 + i - 1] = q2[i];
    solve(l, mid, L, L + cnt1 - 1);
    solve(mid + 1, r, L + cnt1, R);
}

int main() {
    IO::read(n, Q);
    int ccnt = 0, cnt = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            int x;
            IO::read(x);
            w[++ccnt] = x;
            ++cnt;
            q[cnt].x1 = i; q[cnt].yy1 = j;
            q[cnt].k = x;
        }
    for (int i = 1; i <= Q; i++) {
        ++cnt;
        IO::read(q[cnt].x1, q[cnt].yy1, q[cnt].x2, q[cnt].y2, q[cnt].k);
        q[cnt].id = i;
    }
    std::sort(w + 1, w + 1 + ccnt);
    ccnt = std::unique(w + 1, w + 1 + ccnt) - w - 1;
    solve(1, ccnt, 1, cnt);
    for (int i = 1; i <= Q; i++)
        printf("%d\n", ans[i]);
    return 0;
}
View Code

 

posted @ 2020-01-26 14:45  Mrzdtz220  阅读(98)  评论(0编辑  收藏  举报