P3145--题解(鱼币~)
本帖最后由 学习编程中的Ben 于 2024-8-23 10:18 编辑$题目链接: Splitting the Field G$
前言:
本蒟蒻第一篇题解, 存在问题的的地方还请各位多多包涵、指出。
核心思路
本题可以简化成在网格图中有 $n$ 个点,让你圈出 $2$ 个矩形,使得这 $2$ 个矩形面积最小。
1.建立矩阵
题目中指出所有坐标都是正数,于是我们可以 $(0, 0)$ 为锚点,从远到近将所有的点排序.再从第一个点开始枚举,将点的序列分为前后两部分。
$$ ans_{i} = S_{1, i} + S_{i + 1, n} $$
这样分可以将所有的点分成离锚点较近的和距离锚点较远的点,易证没有更优的分法。
2.求矩形面积
通过观察,我们可以发现矩形的长就是这些点中 最大的 $x$ 的值 减去 最小的 $x$ 的值,宽是这些点中 最大的 $y$ 的值 减去 最小的 $y$ 的值。
那我们的问题可以转化成求区间内最值
数据范围是 $ 1 \le n \le 50000 $
我们要枚举每一个点,找到每一个点的最大和最小的 $x$ 和 $y$ 的值,所以需要对查找操作进行优化. 这里推荐使用 $RMQ$.不懂戳这儿 $RMQ$简单介绍
注意事项:
1. 我们应该将 $x, y$ 分别排序,取最小值(只对 $x$ 排序 $80$ 分)
2. 不开 $ long~long $ 见祖宗
3. $RMQ$ 要设置初始值
4. 求出 $ans$ 后要用整个矩形的面积减去 $ans$
代码如下:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, fx, fy, ans = 1e20, t, lx, ly, rx, ry;
struct cow{
int x, y;
}a;
bool cmp1(cow a, cow b){
return a.x < b.x;
}
bool cmp2(cow a, cow b){
return a.y < b.y;
}
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){ if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
void rmq(){
for (int i = 0; i <= n; i++){
for (int j = 0; j <= 30; j++){
fx = fy = 1e20;
}
}
for (int i = 1; i <= n; i++) fx = fx = a.x, fy = fy = a.y;
for (int j = 1; j <= 30; j++){
for (int i = 1; i + (1 << j) - 1 <= n; i++){
fx = min(fx, fx);
fx = max(fx, fx);
fy = min(fy, fy);
fy = max(fy, fy);
}
}
}
int find(int l, int r){
t = log2(r - l + 1);
lx = max(fx, fx);
rx = min(fx, fx);
ly = max(fy, fy);
ry = min(fy, fy);
return (lx - rx) * (ly - ry);
}
signed main() {
n = read();
for (int i = 1; i <= n; i++) a.x = read(), a.y = read();
sort(a + 1, a + 1 + n, cmp1);
rmq();
for (int i = 1; i < n; i++){
int k = find(1, i), q = find(i + 1, n);
ans = min(ans, k + q);
}
sort(a + 1, a + 1 + n, cmp2);
rmq();
for (int i = 1; i < n; i++){
int k = find(1, i), q = find(i + 1, n);
ans = min(ans, k + q);
}
cout << find(1, n) - ans;
return 0;
}
博客食用味更佳: 传送门
去我博客支持一下嘿嘿嘿.毕竟是蒟蒻第一篇题解.管理员还在审核.
@liuhongrun2022 @歌者文明清理员 @~风介~ @zhangjinxuan @不二如是 @柿子饼同学 @陶远航
求评分~(快升级了!!!) 所以说原来是可以LaTeX的。。。 你好,鱼油!
你的题目思路基本上是对的,下面我来帮你简洁的解答一下这个问题。
### 核心思路
P3145题目可以简化为在网格图中分割n个点,使得用两个矩形圈出的面积最小。
### 具体步骤
1. **排序**:
- 由于坐标全是正数,可以以(0, 0)为锚点,对所有点按照某个规则排序(如先按x坐标,再按y坐标排序)。
2. **枚举分割点**:
- 从第一个点开始,尝试将点的序列分为前后两部分,即前i个点和后n-i个点。
3. **计算矩形面积**:
- 对每一部分,分别求出所包含点集的最小和最大x值、y值。
- 矩形面积就等于(最大x - 最小x) * (最大y - 最小y)。
4. **更新最小面积**:
- 对于每一种划分方法,计算两部分的矩形面积总和,并取其中的最小值。
### 算法实现简要描述
def min_area(points):
points.sort()# 根据题意先排序所有点
min_total_area = float('inf')
for i in range(1, len(points)):
left_part = points[:i]
right_part = points
# 计算左部分矩形的边界
min_x1 = min(point for point in left_part)
max_x1 = max(point for point in left_part)
min_y1 = min(point for point in left_part)
max_y1 = max(point for point in left_part)
# 计算右部分矩形的边界
min_x2 = min(point for point in right_part)
max_x2 = max(point for point in right_part)
min_y2 = min(point for point in right_part)
max_y2 = max(point for point in right_part)
# 计算面积
area1 = (max_x1 - min_x1) * (max_y1 - min_y1)
area2 = (max_x2 - min_x2) * (max_y2 - min_y2)
# 更新最小面积
min_total_area = min(min_total_area, area1 + area2)
return min_total_area
以上算法的时间复杂度为 \(O(n \log n)\)(排序) + \(O(n^2)\)(枚举分割和计算面积),在n较小时是可行的。可以通过更复杂的数据结构优化最小最大值的计算以实现进一步的性能提升。
希望这个回答能帮助你更好地理解和解决这个问题。如果有不清楚的地方,欢迎继续提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 {:7_113:} 谢谢啦~@~风介~
等了好久都没几个人回复,评分{:10_266:}
现在论坛怪冷清的.以前这种有鱼币的帖子回复率还是挺高的 {:10_257:} d 👌 {:10_277:} 膜拜orz {:10_256:}{:10_256:} 看看{:10_254:} 谢谢{:10_258:} . OIer 居然跑到这来发题解{:5_106:} 看看 {:10_256:} {:10_249:} 谢谢鱼币 没看懂怎么办
页:
[1]
2