ZOJ Problem Set - 3664 Split the Rectangle

The 2012 ACM-ICPC Asia Changchun Regional Contest-J


题目大一就是去掉某一些使得两个点在同一矩形内,然后问有还剩多少矩形。


实际就是可以搞出一棵二叉树,生成的过程就是矩形分开的过程。然后答案显然就是 叶子节点个数---A和B的LCA为根的子树形的叶节点个数+1。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 3000
using namespace std;
struct  Rect{
        int x1,x2,y1,y2;
        int l,r,sonCnt;
}R[MAXN];
struct  Segment{
        int x1,x2,y1,y2;
}p[MAXN];
struct  Point{
        int x,y;
}A,B;
int N,Q,tot;
bool    innerLine(int v,int L,int R){
        return (v>=L && v<=R);
}
int     buildTree(Rect  node , int flag){
        R[tot]=node;
        R[tot].l=R[tot].r=-1;
        R[tot].sonCnt=0;
        int res = tot++;
        for (int i=0;i<N;++i)
        if ((p[i].y1==p[i].y2)^flag){
           if (!flag) {
                if (p[i].x1==node.x1 && p[i].x2==node.x2 && innerLine(p[i].y1,node.y1,node.y2))
                {
                    Rect temp = node;
                    temp.y1=p[i].y1;
                    R[res].l=  buildTree(temp,!flag);
                    
                    temp = node;
                    temp.y2=p[i].y2;
                    R[res].r= buildTree(temp,!flag);
                }
           } else
           {
                 if (p[i].y1==node.y1 && p[i].y2==node.y2 && innerLine(p[i].x1,node.x1,node.x2))
                 {
                    Rect temp = node;
                    temp.x1=p[i].x1;
                    R[res].l= buildTree(temp,!flag);
                    
                    temp= node;
                    temp.x2=p[i].x2;
                    R[res].r= buildTree(temp,!flag);
                 }
           }
        }
        
        if (R[res].l==-1 && R[res].r==-1) R[res].sonCnt=1;else
        {
            if (R[res].l!=-1) R[res].sonCnt=R[R[res].l].sonCnt;
            if (R[res].r!=-1) R[res].sonCnt+=R[R[res].r].sonCnt;
        }
        return res;
}
bool    innerRect(Point C,Rect R){
        return (C.x>=R.x1 && C.x<=R.x2 && C.y>=R.y1 && C.y<=R.y2);
}
int    DFS(Rect node){
        if (node.l!=-1){
           if (innerRect(A,R[node.l]) && innerRect(B,R[node.l])) 
               return DFS(R[node.l]);
        }
        if (node.r!=-1){
           if (innerRect(A,R[node.r]) && innerRect(B,R[node.r])) 
               return DFS(R[node.r]);
        }
        return node.sonCnt;
}
int main()
{
    while (cin>>R[0].x1>>R[0].y1>>R[0].x2>>R[0].y2){
          cin>>N>>Q;
          for (int i=0;i<N;++i){
              scanf("%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
              if (p[i].x1>p[i].x2) swap(p[i].x1,p[i].x2);
              if (p[i].y1>p[i].y2) swap(p[i].y1,p[i].y2);
          }
          tot=0;
          buildTree(R[0],0);
          for (int i=0;i<Q;++i){
              scanf("%d%d%d%d",&A.x,&A.y,&B.x,&B.y);
              cout<<N+2-DFS(R[0])<<endl;
          }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值