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

CF Gym 100463D Evil 前缀和+离散

时间:2015-07-21 20:14:53      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:

题意:给一些带颜色的点,求一个最小的矩形,恰好包括一半的红色点,且不包括蓝色点。

题解:暴力,求个二维前缀和,用容斥原理更新一下。N很小所以我采用了离散优化,跑了个0ms。

之前没写过二维前缀和,加上离散写得也不是很熟练,所以搞了2个小时,好在是一发就过了。貌似有个坑,线不要特判,不然wa。

#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cstring>

using namespace std;

//#define local

const int maxn = 25;
int Red;

int X[maxn],szx;
int Y[maxn],szy;

int G[maxn][maxn];
int sumb[maxn][maxn];
int suma[maxn][maxn];

struct Poi
{
    int x,y;
    int tp;
    int sx,sy;
    bool operator < (const Poi & rhs) const {
        return x < rhs.x || (x == rhs.x && y < rhs.y);
    }
    void input(){
        scanf("%d%d%d",&x,&y,&tp);
        if(!tp)Red++;
    }
    void GetDis(){
        sx = lower_bound(X,X+szx,x)-X;
        sy = lower_bound(Y,Y+szy,y)-Y;
        G[sx][sy] = tp;
    }
}P[maxn];

const int INF = 0x7fffffff;
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif // local
    int N;
    int cas = 0;
    while(~scanf("%d",&N)&&N){
        Red = 0;
        memset(G,-1,sizeof(G));
        int minx = INF, miny = INF;
        for(int i = 0 ; i < N; i++){
            P[i].input();
            minx = min(minx,P[i].x);
            miny = min(miny,P[i].y);
            //Y[i] = P[i].y;
        }
        X[0] = minx-1; Y[0] = miny-1 ;
        for(int i = 1; i <= N; i++) {
            X[i] = P[i-1].x;
            Y[i] = P[i-1].y;
        }
        sort(X,X+N+1);
        sort(Y,Y+N+1);
        szy = unique(Y,Y+N+1) - Y;
        szx = unique(X,X+N+1) - X;

        memset(suma,0,sizeof(suma));
        memset(sumb,0,sizeof(sumb));

        for(int i = 0; i < N; i++) P[i].GetDis();

        for(int i = 1; i < szx; i++)
        for(int j = 1; j < szy; j++){
            suma[i][j] = suma[i-1][j]+suma[i][j-1]-suma[i-1][j-1]+(G[i][j]==1);
            sumb[i][j] = sumb[i-1][j]+sumb[i][j-1]-sumb[i-1][j-1]+(G[i][j]==0);
        }
        Red >>= 1;
        int area = INF;
        for(int lx = 0; lx < szx; lx++){
            for(int rx = lx+1; rx < szx; rx++){
                for(int ly = 0; ly <szy; ly++){
                    for(int ry = ly+1; ry < szy; ry++){
                        if(suma[rx][ry]-suma[rx][ly]-suma[lx][ry]+suma[lx][ly]) continue;
                        if(Red == sumb[rx][ry]-sumb[rx][ly]-sumb[lx][ry]+sumb[lx][ly]){
                                area = min(area,(X[rx]-X[lx+1])*(Y[ry]-Y[ly+1]));
                        }
                    }
                }
            }
        }
        printf("Case %d: %d\n",++cas,area!=INF?area:-1);
    }
    return 0;
}

 

CF Gym 100463D Evil 前缀和+离散

标签:

原文地址:http://www.cnblogs.com/jerryRey/p/4665299.html

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