CF Gym 100463D Evil (二维前缀和+离散)

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

题解:暴力,求个二维前缀和,用容斥原理更新一下。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;

}

 

你可能感兴趣的:(vi)