zoukankan      html  css  js  c++  java
  • Memento Mori (二维前缀和 + 枚举剪枝)

    枚举指的是枚举矩阵的上下界,然后根据p0, p1, p2的关系去找出另外的中间2个点。然后需要记忆化一些地方防止重复减少时间复杂度。这应该是最关键的一步优化时间,指的就是代码中to数组。然后就是子矩阵的一个计算了,需要用二维前缀和预处理数据,然后判断的时候直接O(1)查询就好了。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int inf  = 0x3f3f3f3f;
    const int maxn = 2e3 + 7;
    struct node{
        int x, y;
        node(){}
        node(int x, int y) : x(x), y(y){}
    }a[maxn], b[maxn], c[maxn], X[4];
    int p[4], matdp[maxn][maxn], to[maxn][2];
    
    bool cmp1(const node &a, const node &b){
        return a.x < b.x;
    }
    bool cmp2(const node &a, const node &b){
        return a.y > b.y;
    }
    bool cmp3(const node &a, const node &b){
        return a.y < b.y;
    }
    
    int howmany(int x1, int y1, int x2, int y2){
        return matdp[x2][y2] + matdp[x1 - 1][y1 - 1] - matdp[x1 - 1][y2] - matdp[x2][y1 - 1];
    }
    bool isOK(){
        int x1 = inf, y1 = inf, x2 = 0, y2 = 0;
        for(int i = 0; i < 4; i ++){
            x1 = min(x1, X[i].x); x2 = max(x2, X[i].x);
            y1 = min(y1, X[i].y); y2 = max(y2, X[i].y);
            for(int j = i + 1; j < 4; j ++)
                if((p[j] - p[i]) * (X[j].y - X[i].y) <= 0) return false;
        }
        return howmany(x1, y1, x2, y2) == 4;
    }
    
    int main(){
        int T, n, m, k, x, y;scanf("%d",&T);
        while(T --){
            scanf("%d%d%d", &n, &m, &k);
            scanf("%d%d%d%d", &p[0], &p[1], &p[2], &p[3]);
            int big = 0, small = 0, ans = 0;
            (p[0] > p[1]) ? small ++ : big ++;
            (p[0] > p[2]) ? small ++ : big ++;
            memset(matdp, 0, sizeof(matdp));
            for(int i = 1; i <= k; i ++){
                scanf("%d%d", &x, &y);matdp[x][y] = 1;
                a[i] = b[i] = c[i] = node(x, y);
            }
            for(int i = 1; i <= n; i ++){
                for(int j = 1; j <= m; j ++)
                    matdp[i][j] += matdp[i][j - 1];
                for(int j = 1; j <= m; j ++)
                    matdp[i][j] += matdp[i - 1][j];
            }
            sort(a + 1, a + k + 1, cmp1);
            sort(b + 1, b + k + 1, cmp2);
            sort(c + 1, c + k + 1, cmp3);
            for(int i = 1; i <= k; i ++){
                X[0] = a[i];
                for(int j = 0; j <= k; j ++)
                    to[j][0] = to[j][1] = j == k ? 0 : j + 1;
                for(int j = k; j > i; j --){
                    if(a[i].x == a[j].x) break;
                    if((p[3] - p[0]) * (a[j].y - a[i].y) <= 0) continue;
                    X[3] = a[j]; X[1] = X[2] = node(-1, -1);
                    int u = 0, v, bi = big, sm = small, t = 1;
                    while(sm --){
                        for(v = u, u = to[u][0]; u; to[v][0] = to[u][0], v = u, u = to[u][0])
                            if(a[i].x < b[u].x && b[u].x < a[j].x && b[u].y < a[i].y){
                                X[t ++] = b[u];break;
                            }
                    }
                    u = 0;
                    while(bi --){
                        for(v = u, u = to[u][1]; u; to[v][1] = to[u][1], v = u, u = to[u][1])
                            if(a[i].x < c[u].x && c[u].x < a[j].x && c[u].y > a[i].y){
                                X[t ++] = c[u];break;
                            }
                    }
                    if(t < 3 || X[1].x == X[2].x) continue;
                    if(X[1].x > X[2].x) swap(X[1], X[2]);
                    if(isOK()) ans ++;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    085 Maximal Rectangle 最大矩形
    084 Largest Rectangle in Histogram 柱状图中最大的矩形
    083 Remove Duplicates from Sorted List 有序链表中删除重复的结点
    082 Remove Duplicates from Sorted List II 有序的链表删除重复的结点 II
    081 Search in Rotated Sorted Array II 搜索旋转排序数组 ||
    080 Remove Duplicates from Sorted Array II 从排序阵列中删除重复 II
    079 Word Search 单词搜索
    078 Subsets 子集
    bzoj2326: [HNOI2011]数学作业
    bzoj2152: 聪聪可可
  • 原文地址:https://www.cnblogs.com/wethura/p/9788932.html
Copyright © 2011-2022 走看看