zoukankan      html  css  js  c++  java
  • 「JSOI2015」symmetry

    「JSOI2015」symmetry

    传送门

    我们先考虑构造出原正方形经过 (4) 种轴对称变换以及 (2) 种旋转变换之后的正方形都构造出来,然后对所得的 (7) 个正方形都跑一遍二维哈希,这样我们就可以通过哈希,在 (O(n ^ 2)) 时间内判断原正方形中是否存在某一类型的某一大小的子正方形。

    但是如果我们枚举边长,复杂度就会达到 (O(n ^ 3)) 级别,显然过不了。

    考虑优化:我们发现对于任意一种类型的正方形,它把最外面一圈去掉之后还是满足原来的性质,所以我们可以二分来求。需要注意的是我们不好同时计算奇数边长和偶数边长的正方形,所以要二分两次。

    参考代码:

    #include <cstdio>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    template < class T > inline T max(T a, T b) { return a > b ? a : b; }
    template < class T > inline void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
     
    typedef unsigned long long ull;
    const int _ = 502;
    const ull base1 = 19491001, base2 = 19260817;
    int n; ull pw1[_], pw2[_], h[7][_][_];
     
    inline ull gethash(int k, int x1, int y1, int x2, int y2) {
        int w = x2 - x1 + 1;
        return h[k][x2][y2] - h[k][x1 - 1][y2] * pw1[w] - h[k][x2][y1 - 1] * pw2[w] + h[k][x1 - 1][y1 - 1] * pw1[w] * pw2[w];
    }
     
    inline bool check_90(int x1, int y1, int x2, int y2) {
        return gethash(0, x1, y1, x2, y2) == gethash(5, y1, n - x2 + 1, y2, n - x1 + 1);
    }
     
    inline bool check_180(int x1, int y1, int x2, int y2) {
        return gethash(0, x1, y1, x2, y2) == gethash(6, n - x2 + 1, n - y2 + 1, n - x1 + 1, n - y1 + 1);
    }
     
    inline bool check_diag(int x1, int y1, int x2, int y2) {
        return gethash(0, x1, y1, x2, y2) == gethash(1, x1, n - y2 + 1, x2, n - y1 + 1)
            || gethash(0, x1, y1, x2, y2) == gethash(2, n - x2 + 1, y1, n - x1 + 1, y2)
            || gethash(0, x1, y1, x2, y2) == gethash(3, y1, x1, y2, x2)
            || gethash(0, x1, y1, x2, y2) == gethash(4, n - y2 + 1, n - x2 + 1, n - y1 + 1, n - x1 + 1);
    }
     
    inline bool check_4(int x1, int y1, int x2, int y2) {
        return check_180(x1, y1, x2, y2) && check_diag(x1, y1, x2, y2);
    }
     
    inline bool check_8(int x1, int y1, int x2, int y2) {
        return check_90(x1, y1, x2, y2) && check_diag(x1, y1, x2, y2);
    }
     
    template < class T > inline bool check(T f, int x) {
        for (rg int i = x; i <= n; ++i)
            for (rg int j = x; j <= n; ++j)
                if  (f(i - x + 1, j - x + 1, i, j)) return 1;
        return 0;
    }
     
    template < class T > inline int solve(T f) {
        int res = 0, l, r, mid;
        l = 0, r = (n - 1) >> 1;
        while (l < r) {
            mid = (l + r + 1) >> 1;
            if (check(f, mid << 1 | 1)) l = mid; else r = mid - 1;
        }
        res = max(res, l << 1 | 1);
        l = 1, r = n >> 1;
        while (l < r) {
            mid = (l + r + 1) >> 1;
            if (check(f, mid << 1)) l = mid; else r = mid - 1;
        }
        res = max(res, l << 1);
        return res;
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        read(n);
        for (rg int i = 1; i <= n; ++i)
            for (rg int j = 1; j <= n; ++j) {
                scanf("%1d", &h[0][i][j]);
                h[1][i][n - j + 1] = h[0][i][j];
                h[2][n - i + 1][j] = h[0][i][j];
                h[3][j][i] = h[0][i][j];
                h[4][n - j + 1][n - i + 1] = h[0][i][j];
                h[5][j][n - i + 1] = h[0][i][j];
                h[6][n - i + 1][n - j + 1] = h[0][i][j];
            }
        pw1[0] = 1; for (rg int i = 1; i <= n; ++i) pw1[i] = pw1[i - 1] * base1;
        pw2[0] = 1; for (rg int i = 1; i <= n; ++i) pw2[i] = pw2[i - 1] * base2;
        for (rg int k = 0; k < 7; ++k) {
            for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= n; ++j) h[k][i][j] += h[k][i - 1][j] * base1;
            for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= n; ++j) h[k][i][j] += h[k][i][j - 1] * base2;
        }
        printf("%d %d %d %d %d
    ", solve(check_8), solve(check_90), solve(check_4), solve(check_180), solve(check_diag));
        return 0;
    }
    
  • 相关阅读:
    快乐
    端午节杂记
    消失一段时间
    做好自己,做最好的自己
    童童的儿童节
    *完成第一个Java的程序(Jogl的一个窗口框架)
    *JS实现HashTable的例子
    *JavaScript检查ActiveX控件是否已经安装过
    *DOS命令REG操作注册表
    *汇总c#.net常用函数和方法集
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12364609.html
Copyright © 2011-2022 走看看