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

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

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/3916362e5d0a 在C#编程平台下,构建一个曲线编辑器是一项融合了图形用户界面(GUI)构建、数据管理及数学运算的应用开发任务。 接下来将系统性地介绍这个曲线编辑器开发过程中的核心知识点:1. **定制曲线面板展示数据曲线**: - 控件选用:在C#的Windows Forms或WPF框架中,有多种控件可用于曲线呈现,例如PictureBox或用户自定义的UserControl。 通过处理重绘事件,借助Graphics对象执行绘图动作,如运用DrawCurve方法。 - 数据图形化:通过线性或贝塞尔曲线连接数据点,以呈现数据演变态势。 这要求掌握直线与曲线的数学描述,例如两点间的直线公式、三次贝塞尔曲线等。 - 坐标系统与缩放比例:构建X轴和Y轴,设定坐标标记,并开发缩放功能,使用户可察看不同区间内的数据。 2. **在时间轴上配置多个关键帧数据**: - 时间轴构建:开发一个时间轴组件,显示时间单位刻度,并允许用户在特定时间点设置关键帧。 时间可表现为连续形式或离散形式,关键帧对应于时间轴上的标识。 - 关键帧维护:利用数据结构(例如List或Dictionary)保存关键帧,涵盖时间戳和关联值。 需考虑关键帧的添加、移除及调整位置功能。 3. **调整关键帧数据,通过插值方法获得曲线**: - 插值方法:依据关键帧信息,选用插值方法(如线性插值、样条插值,特别是Catmull-Rom样条)生成平滑曲线。 这涉及数学运算,确保曲线在关键帧之间无缝衔接。 - 即时反馈:在编辑关键帧时,即时刷新曲线显示,优化用户体验。 4. **曲线数据的输出**: - 文件类型:挑选适宜的文件格式存储数据,例如XML、JSON或...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值