hdu 4429 Split the Rectangle(lca+二叉树)

本文介绍了一个基于矩形分割的游戏算法,玩家需要通过绘制线段来分割初始矩形,并解决如何通过删除部分线段使得两个指定点位于同一空白矩形内的同时,最大化剩余空白矩形数量的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Split the Rectangle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 699    Accepted Submission(s): 247


Problem Description
Alice comes up with a new game and wants to play with Bob.
There is one rectangle on the paper initially, we define its lower-left corner's coordinate is (xL, yL) and upper-right corner's coordinate is (xR, yR).
Bob has executed the step as description below N times:
Bob should select one empty rectangle. If the rectangle is the initial one or is split by one vertical segment, he should split it into two parts by drawing one horizontal segment; otherwise he should split the rectangle into two parts by drawing one vertical segment. An empty rectangle means there is no segment in this rectangle except its only four boundary segments.
You should pay attention that there are only two kinds segments: vertical segment and horizontal segment.
Now Bob has several queries. In each query, Bob selects two target points in the paper. (You can assume that all given target points are always located inside the initial rectangle and not in any drawing segments.) He wants Alice to answer the question as soon as possible: Alice can erase several existing segments, and make two target points in one empty rectangle, and she should answer how many empty rectangles at most would be left at last.
But there are some restrictions: Alice cannot erase segments of the initial rectangle (the (xL, yL) to (xR, yR) one), she can only erase segments drew by Bob; if Alice want to erase one segment, both sides of the segment must be empty rectangles, and after erase it, the two empty rectangles must combine to one bigger empty rectangle; if erasing an existing segment will lead to a disconnected graph, the operation is forbidden.

 

Input
There are multiple test cases.
The first line contains four integers xL, yL, xR, yR indicating the coordinates of the lower-left corner and the upper-right corner of the initial huge rectangle respectively. (-100,000 <= xL, yL, xR, yR <= 100,000, xL< xR, yL< yR)
The next line contains two integers N and Q. (1 <= N, Q <= 1000)
The next N lines each line contains four integers x1, y1, x2, y2 indicating the coordinates of two endpoints of one drawing segments. (-100,000 <= x1, y1, x2, y2 <= 100,000, x1=x2 | y1=y2)
The next Q lines each line contains four integers xA, yA, xB, yB indicating the coordinates of two target points in this query. (-100,000 <= xA, yA, xB, yB <= 100,000).

 

Output
For each test case, output Q lines, output the answer of each query in each line.
 

Sample Input
-10 -10 10 10 5 1 -10 0 10 0 5 -10 5 0 -5 0 -5 10 -5 5 10 5 5 -5 10 -5 0 -3 7 -3 0 0 4 4 3 2 0 2 4 2 2 0 2 2 2 2 2 4 1 1 1 3 1 1 3 1 -10 -10 10 10 3 4 -10 0 10 0 0 -10 0 0 0 0 0 10 -9 -9 -8 -8 -9 -9 -9 9 -9 -9 9 -9 -9 -9 9 9
 

Sample Output
4 1 3 4 1 3 1

题意:

给定一个矩形,并给出n条线段,每个线段会将空白的矩形划分成两块。现给出两个点,问通过删除线段的方法能让两个点在同一块空白矩形的时候最多能剩多少个空白矩形?

思路:

每次线段划分矩形的时候都会划分成左右两块矩形。于是可以将这个二维的图建成一棵树。保存线段划分成左右子图的状态。在询问时,寻找他们的最近公共祖先。然后答案就是num[0]-num[pos]+1。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=2005;
int num[maxn];//表示子图的数量
struct rec
{
    int lx,ly,rx,ry;
    int fath,lson,rson,dep;
}q[maxn];
int find(int x,int y)
{
    int r=0,t;
    while(1)
    {
        if(q[r].lson==0) return r;
        t=q[r].lson;
        if(x>=q[t].lx&&x<=q[t].rx&&y>=q[t].ly&&y<=q[t].ry)
            r=t;
        else
            r=q[r].rson;
    }
}
int get_num(int u)
{
    num[u]=0;
    if(q[u].lson==0) return num[u]=1;
    else
    {
        num[u]+=get_num(q[u].lson);
        num[u]+=get_num(q[u].rson);
    }
    return num[u];
}
int lca(int lx,int ly,int rx,int ry)
{
    int a=find(lx,ly);
    int b=find(rx,ry);
    while(a!=b)
    {
        if(q[a].dep<q[b].dep)
            b=q[b].fath;
        else if(q[a].dep>q[b].dep)
            a=q[a].fath;
        else
        {
            a=q[a].fath;
            b=q[b].fath;
        }
    }
    return a;
}
int main()
{
    int lx,ly,rx,ry,n,w,now;
    while(~scanf("%d%d%d%d",&lx,&ly,&rx,&ry))
    {
        now=0;
        q[now++]=(rec){lx,ly,rx,ry,-1,0,0,0};
        scanf("%d%d",&n,&w);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
            if(lx>rx) swap(lx,rx);
            if(ly>ry) swap(ly,ry);
            int mx=(lx+rx)/2,my=(ly+ry)/2;
            int pos=find(mx,my);
            int dep=q[pos].dep;
            q[pos].lson=now;
            q[now]=(rec){q[pos].lx,q[pos].ly,rx,ry,pos,0,0,dep+1};
            now++;
            q[pos].rson=now;
            q[now]=(rec){lx,ly,q[pos].rx,q[pos].ry,pos,0,0,dep+1};
            now++;
        }
        get_num(0);
        for(int i=1;i<=w;i++)
        {
            scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
            int pos=lca(lx,ly,rx,ry);
            printf("%d\n",num[0]-num[pos]+1);
        }
    }
    return 0;
}



资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值