zoukankan      html  css  js  c++  java
  • BZOJ2146 Construct

    题目大意

    给出一个多边形A(保证边平行于坐标轴),要用另一个多边形B(边也必须平行于坐标轴)把A围起来,求:

    1)B的最小周长;

    2)B在满足1)的前提下的最小面积。

    输入输出

    输入A的边数N,和N个顶点的坐标(均为整数)。

    输出1)和2)的答案,各占一行。

    数据范围

    4≤N≤100000,坐标的绝对值≤1e9

    解析

    1)对于第一问,可以把B等价为一个边平行于坐标轴的矩形,于是答案显而易见的等于(max_x – min_x + max_y – min_y) * 2;(然而我最开始SB地求了个凸包……)

    2)对于第二问,为了满足B的边长最小,“凹进去”的边显然不可取,由于边平行于坐标轴,我们可以把点按x排序,上下两个单调栈维护y,需要注意的是只有当出现“凹”形的时候才能pop,也就是说实际上维护的是一个“峰”(大概不叫单调栈了):

    clip_image002

    还有就是y相等的点不能直接pop掉。

    然后从左到右一段一段地算面积加入答案即可,具体见代码。

    代码

    求了凸包的版本:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <iomanip>
      5 #include <cmath>
      6 #include <algorithm>
      7 
      8 typedef long long LL;
      9 const LL INF = 0x3f3f3f3f3f3f3f3f;
     10 struct Point {
     11     LL x, y;
     12     Point(LL _x = 0, LL _y = 0):x(_x), y(_y) {};
     13     Point operator -(const Point &) const;
     14     bool operator <(const Point &) const;
     15     friend LL cross(const Point &, const Point &);
     16 } point[100010];
     17 int N, convex[100010], tail;
     18 
     19 void calculate_convex();
     20 LL calculate_perimeter();
     21 LL calculate_area();
     22 
     23 int main() {
     24 #ifndef ONLINE_JUDGE
     25     freopen("2146.in", "r", stdin);
     26     freopen("2146.out", "w", stdout);
     27 #endif
     28     std::ios::sync_with_stdio(false);
     29     std::cin >> N;
     30     for (int i = 0; i < N; i++)
     31         std::cin >> point[i].x >> point[i].y;
     32     std::sort(point, point + N);
     33     calculate_convex();
     34     std::cout << calculate_perimeter() << std::endl << calculate_area() << std::endl;
     35 
     36     return 0;
     37 }
     38 Point Point::operator -(const Point &p) const { return Point(x - p.x, y - p.y); }
     39 bool Point::operator <(const Point &p) const { return x == p.x ? y < p.y : x < p.x; }
     40 LL cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
     41 void calculate_convex() {
     42     for (int i = 0; i < N; i++) {
     43         while (tail > 1 && cross(point[convex[tail - 1]] - point[convex[tail - 2]], point[i] - point[convex[tail - 1]]) >= 0)
     44             tail--;
     45         convex[tail++] = i;
     46     }
     47     int size_up = tail - 1;
     48     for (int i = N - 2; i >= 0; i--) {
     49         while (tail - size_up > 1 && cross(point[convex[tail - 1]] - point[convex[tail - 2]], point[i] - point[convex[tail - 1]]) >= 0)
     50             tail--;
     51         convex[tail++] = i;
     52     }
     53     tail--;
     54 }
     55 LL calculate_perimeter() {
     56     LL res = 0;
     57     for (int i = 0; i < tail; i++) {
     58         res += abs(point[convex[i]].x - point[convex[i + 1]].x);
     59         res += abs(point[convex[i]].y - point[convex[i + 1]].y);
     60     }
     61     return res;
     62 }
     63 LL calculate_area() {
     64     int stk1[100010], top1 = 0, stk2[100010], top2 = 0;
     65     LL res = 0, maxy = -INF, miny = INF;
     66     for (int i = 0; i < N; i++) {
     67         while (top1 > 0 && point[i].y > point[stk1[top1 - 1]].y && maxy > point[stk1[top1 - 1]].y)
     68             --top1;
     69         stk1[top1++] = i;
     70         maxy = std::max(maxy, point[i].y);
     71         while (top2 > 0 && point[i].y < point[stk2[top2 - 1]].y && miny < point[stk2[top2 - 1]].y)
     72             --top2;
     73         stk2[top2++] = i;
     74         miny = std::min(miny, point[i].y);
     75     }
     76     LL tmp1 = point[stk1[0]].y, tmp2 = point[stk2[0]].y;
     77     for (int i = 0, j = 0, lastx = point[0].x; i < top1;) {
     78         while (j < top2 && point[stk2[j]].x <= point[stk1[i]].x) {
     79             res += (point[stk2[j]].x - lastx) * (tmp1 - tmp2);
     80             lastx = point[stk2[j]].x;
     81             ++j;
     82             if (j < top2) tmp2 = std::max(point[stk2[j]].y, point[stk2[j - 1]].y);
     83             else tmp2 = point[stk2[j - 1]].y;
     84         }
     85         res += (point[stk1[i]].x - lastx) * (tmp1 - tmp2);
     86         lastx = point[stk1[i]].x;
     87         ++i;
     88         tmp1 = std::min(point[stk1[i]].y, point[stk1[i - 1]].y);
     89     }
     90     return res;
     91 }

    正常版本:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <iomanip>
      5 #include <cmath>
      6 #include <algorithm>
      7 
      8 typedef long long LL;
      9 const LL INF = 0x3f3f3f3f3f3f3f3f;
     10 struct Point {
     11 	LL x, y;
     12 	Point(LL _x = 0, LL _y = 0):x(_x), y(_y) {};
     13 	bool operator <(const Point &) const;
     14 } point[100010];
     15 int N;
     16 
     17 LL calculate_perimeter();
     18 LL calculate_area();
     19 
     20 int main() {
     21 #ifndef ONLINE_JUDGE
     22 	freopen("2146.in", "r", stdin);
     23 	freopen("2146.out", "w", stdout);
     24 #endif
     25 	std::ios::sync_with_stdio(false);
     26 	std::cin >> N;
     27 	for (int i = 0; i < N; i++)
     28 		std::cin >> point[i].x >> point[i].y;
     29 	std::sort(point, point + N);
     30 	std::cout << calculate_perimeter() << std::endl << calculate_area() << std::endl;
     31 
     32 	return 0;
     33 }
     34 bool Point::operator <(const Point &p) const { return x == p.x ? y < p.y : x < p.x; }
     35 LL calculate_perimeter() {
     36 	LL maxx = -INF, minx = INF, maxy = -INF, miny = INF;
     37 	for (int i = 0; i < N; i++) {
     38 		maxx = std::max(maxx, point[i].x);
     39 		minx = std::min(minx, point[i].x);
     40 		maxy = std::max(maxy, point[i].y);
     41 		miny = std::min(miny, point[i].y);
     42 	}
     43 	return (maxx - minx + maxy - miny) << 1;
     44 }
     45 LL calculate_area() {
     46 	int stk1[100010], top1 = 0, stk2[100010], top2 = 0;
     47 	LL res = 0, maxy = -INF, miny = INF;
     48 	for (int i = 0; i < N; i++) {
     49 		while (top1 > 0 && point[i].y > point[stk1[top1 - 1]].y && maxy > point[stk1[top1 - 1]].y)
     50 			--top1;
     51 		stk1[top1++] = i;
     52 		maxy = std::max(maxy, point[i].y);
     53 		while (top2 > 0 && point[i].y < point[stk2[top2 - 1]].y && miny < point[stk2[top2 - 1]].y)
     54 			--top2;
     55 		stk2[top2++] = i;
     56 		miny = std::min(miny, point[i].y);
     57 	}
     58 	LL tmp1 = point[stk1[0]].y, tmp2 = point[stk2[0]].y;
     59 	for (int i = 0, j = 0, lastx = point[0].x; i < top1;) {
     60 		while (j < top2 && point[stk2[j]].x <= point[stk1[i]].x) {
     61 			res += (point[stk2[j]].x - lastx) * (tmp1 - tmp2);
     62 			lastx = point[stk2[j]].x;
     63 			++j;
     64 			if (j < top2) tmp2 = std::max(point[stk2[j]].y, point[stk2[j - 1]].y);
     65 			else tmp2 = point[stk2[j - 1]].y;
     66 		}
     67 		res += (point[stk1[i]].x - lastx) * (tmp1 - tmp2);
     68 		lastx = point[stk1[i]].x;
     69 		++i;
     70 		tmp1 = std::min(point[stk1[i]].y, point[stk1[i - 1]].y);
     71 	}
     72 	return res;
     73 }
  • 相关阅读:
    最大子数组求和并进行条件组合覆盖测试
    Ubuntu 16.04 c++ Google框架单元测试
    The directory '/home/stone/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If execu
    Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh > /dev/null; fi'
    个人博客作业三:微软小娜APP的案例分析
    补交 作业一
    补交 作业二:个人博客作业内容:需求分析
    嵌入式软件设计第12次实验报告
    嵌入式软件设计第11次实验报告
    嵌入式软件设计第10次实验报告
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10265529.html
Copyright © 2011-2022 走看看