码迷,mamicode.com
首页 > 其他好文 > 详细

Memento Mori (二维前缀和 + 枚举剪枝)

时间:2018-10-15 01:17:39      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:判断   bsp   any   scan   nbsp   inf   max   bit   需要   

枚举指的是枚举矩阵的上下界,然后根据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\n",ans);
    }
    return 0;
}

 

Memento Mori (二维前缀和 + 枚举剪枝)

标签:判断   bsp   any   scan   nbsp   inf   max   bit   需要   

原文地址:https://www.cnblogs.com/wethura/p/9788932.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!