bzoj2738 矩阵乘法

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2738

【题解】

整体二分,然后用二维树状数组(单点修改区间查询)统计即可。

不知道为什么跑的特别慢(可能是我的整体二分常数太大?)

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10, N = 510;
const int mod = 1e9+7;

# define RG register
# define ST static

inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x<<3) + (x<<1) + ch - '0';
        ch = getchar();
    }
    return x*f;
}

int n, Q;
struct quest {
    int x1, y1, x2, y2, k;
    quest() {}
    quest(int x1, int y1, int x2, int y2, int k) : x1(x1), y1(y1), x2(x2), y2(y2), k(k) {}
    inline void set() {
        x1 = read(), y1 = read(), x2 = read(), y2 = read(), k = read();
    }
}a[M];

struct pa {
    int x, y, d;
    pa() {}
    pa(int x, int y, int d) : x(x), y(y), d(d) {}
    friend bool operator < (pa a, pa b) {
        return a.d < b.d;
    }
}p[M]; int pn = 0;


struct BIT {
    int c[N][N];
    # define lb(x) (x&(-x))
    inline void set(int _n) {
        n = _n;
        memset(c, 0, sizeof c);
    }
    inline void edt(int x, int y, int d) {
        for (int i=x; i<=n; i+=lb(i))
            for (int j=y; j<=n; j+=lb(j))
                c[i][j] += d;
    }
    inline int sum(int x, int y) {
        int ret = 0;
        for (int i=x; i; i-=lb(i))
            for (int j=y; j; j-=lb(j))
                ret += c[i][j];
        return ret;
    }
    inline int sum(int x1, int y1, int x2, int y2) {
        return sum(x2, y2) - sum(x2, y1-1) - sum(x1-1, y2) + sum(x1-1, y1-1);
    }
}T;
                
int id[M], ans[M], cur[M], t1[M], t2[M];
inline void solve(int l, int r, int al, int ar, int fr) {
    if(al > ar) return ;
    if(l == r) {
        for (int i=al; i<=ar; ++i) ans[id[i]] = l;
        return ;
    }
//    printf("%d %d %d %d %d
", l, r, al, ar, fr);
    int mid = l+r>>1, ed, t1n, t2n; t1n = t2n = 0;
    for (ed=fr; ed<=pn; ++ed) {
        if(p[ed].d > mid) break;
        T.edt(p[ed].x, p[ed].y, 1);
    }
    for (int i=al, t; i<=ar; ++i) {
        int x = id[i];
        if((t = cur[x] + T.sum(a[x].x1, a[x].y1, a[x].x2, a[x].y2)) >= a[x].k) t1[++t1n] = x;
        else t2[++t2n] = x, cur[x] = t;
//        printf("id = %d, t = %d
", x, t);
    }
//    printf("%d %d
", t1n, t2n);
    for (int i=fr; i<ed; ++i) T.edt(p[i].x, p[i].y, -1);
    int tn = al-1;
    for (int i=1; i<=t1n; ++i) id[++tn] = t1[i];
    t1n = tn;
    for (int i=1; i<=t2n; ++i) id[++tn] = t2[i];
    solve(l, mid, al, t1n, fr);
    solve(mid+1, r, t1n+1, ar, ed);        
}

int main() {
    int mx = 0;
    n = read(), Q = read();
    T.set(n);
    for (int i=1, t; i<=n; ++i) 
        for (int j=1; j<=n; ++j) {
            t = read();
            mx = max(mx, t);
            p[++pn] = pa(i, j, t);
        }
    sort(p+1, p+pn+1);
    for (int i=1; i<=Q; ++i) id[i] = i, a[i].set();
    solve(0, mx, 1, Q, 1);
    for (int i=1; i<=Q; ++i) printf("%d
", ans[i]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/galaxies/p/bzoj2738.html