HDU-3648 Median Filter 树状数组求中位数

HDU-3648 Median Filter 树状数组求中位数

参考:http://blog.jobbole.com/96430/

遍历和二分写的比较麻烦。
最后还要注意避免 Presentation Error:行尾有空格。

// Median Filter
// http://acm.hdu.edu.cn/showproblem.php?pid=3648

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>

using namespace std;

typedef long long LL;
const int maxn = 510;
const int maxg = 1000010;

int n, r;
int m[maxn][maxn];
int newm[maxn][maxn];
int a[maxg];
int maxcolor = 0;

inline int lowbit(int x) { return x & -x; }

void add(int x, int v) {
    for (int i = x; i < maxcolor + 10; i += lowbit(i)) {
        a[i] += v;
    }
}

int sum(int x) {
    int s = 0;
    for (int i = x; i ; i -= lowbit(i)) {
        s += a[i];
    }
    return s;
}

void median_filter(int r) {
    for (int i = 1; i <= r+r+1; i++) {
        for (int j = 1; j <= r+r; j++) {
            add(m[i][j], 1);
        }
    }

    for (int i = r + 1; i <= n - r; i++) {
        if ( (i - r) & 1 ) {
            for (int j = r + 1; j <= n - r; j++) {
                for (int k = i - r; k <= i + r; k++) {
                    add(m[k][j+r], 1);
                }
                int left = 1, right = maxcolor+1, mid;
                int median = (r+r+1) * (r+r+1) / 2;
                while (left < right) {
                    mid = (left + right) >> 1;
                    if (sum(mid) <= median) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                newm[i][j] = left;
                for (int k = i - r; k <= i + r; k++) {
                    add(m[k][j-r], -1);
                }
            }

            if (i < n-r) {
                for (int k = n-r-r+1; k <= n; k++) {
                    add(m[i-r][k], -1);
                    add(m[i+r+1][k], 1);
                }
            }
        } else {
            for (int j = n - r; j >= r + 1; j--) {
                for (int k = i - r; k <= i + r; k++) {
                    add(m[k][j-r], 1);
                }

                int left = 1, right = maxcolor+1, mid;
                int median = (r+r+1) * (r+r+1) / 2;
                while (left < right) {
                    mid = (left + right) >> 1;
                    if (sum(mid) <= median) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                newm[i][j] = left;

                for (int k = i - r; k <= i + r; k++) {
                    add(m[k][j+r], -1);
                }
            }

            if (i < n-r) {
                for (int k = r+r; k >= 1; k--) {
                    add(m[i-r][k], -1);
                    add(m[i+r+1][k], 1);
                }
            }
        }
    }
}

int main() {
    while (cin >> n >> r) {
        if (!n && !r) break;
        maxcolor = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                scanf("%d", &m[i][j]);
                m[i][j]++;
                if (maxcolor < m[i][j])
                    maxcolor = m[i][j];
            }
        }
        memset(a, 0, (maxcolor + 10) * sizeof(int));
        median_filter(r);
        for (int i = r+1; i <= n-r; i++) {
            for (int j = r+1; j <= n-r; j++) {
                printf("%d ", newm[i][j]-1);
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cyz14/article/details/79269405
今日推荐