zoukankan      html  css  js  c++  java
  • jzoj 2866. 【集训队互测 2012】Bomb

    Description

    给你(n)个点,坐标分别为((xi,yi))。从中取出三个点,使得其两两间曼哈顿距离和最大和最小,求最大值和最小值。
    对于 100% 的数据, N<=100000 , 0<=Xi,Yi<=10^8

    Solution

    看完题目后感觉要分类讨论,思考1h后果断暴力O(n^3)。
    但是判断了一下n<=500才跑暴力,得了30分。(™10^9过4s?不判50分)
    其实可以O(n2)暴力的。(听说O(n2)+优化 = 100)
    对于第一个最大值,我们可以(O(n))求出。
    我们先扫一遍(n)个点,可以得到最大和最小的(x)以及最大和最小的(y)
    然后我们再枚举每个点,而其所组成的三个点的最大值便是(2 * max(maxx - a[i].x, a[i].x - minx) + 2 * max(maxy - a[i].y, a[i].y - miny))
    因为它所组成的矩形是最长的长和最长的宽,所以值便是最大的。
    这是运用了贪心的思想,可以感性理解一下。
    然后我们再求最小值。
    这里使用(O(n^2))的方法+优化的。
    我们先将点按照(x)从小到大排序。
    对于三个点:((x1, y1),(x2, y2),(x3, y3))
    (x1 < x2 < x3),所以关于(x)的答案就应该是:
    ((x2 - x1) + (x3 - x2) + (x3 - x1))
    (=2 * (x3 - x1))
    我们发现与(x2)无关。
    所以我们只需枚举两个点,即可得到有关(x)的答案。
    (y)呢,我们便只需在线维护一个(i) ~ (j)的与(a[i].y,a[j].y)的差的最小值即可。
    (if (a[j].x - a[i].x >= ans2) break;)
    这个优化正确性显然。

    Code

    #include <cstdio>
    #include <algorithm>
    #define N 100010
    #define fo(x, a, b) for (int x = a; x <= b; x++)
    #define fd(x, a, b) for (int x = a; x >= b; x--)
    using namespace std;
    struct node{int x, y;}a[N];
    int n, m, maxy, miny, up, down, s, s1;
    int ans1, ans2 = 2e9;
    bool pd;
    
    inline int read()
    {
    	int x = 0; char c = getchar();
    	while (c < '0' || c > '9') c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return x;
    }
    
    inline int cmp(node x, node y) {return x.x < y.x;}
    
    inline int max(int x, int y) {return x > y ? x : y;}
    
    inline int min(int x, int y) {return x < y ? x : y;}
    
    int main()
    {
    	freopen("bomb.in", "r", stdin);
    	freopen("bomb.out", "w", stdout); 
    	n = read();
    	a[1].x = read();
    	maxy = miny = a[1].y = read();
    	fo(i, 2, n)
    	{
    		a[i].x = read(), a[i].y = read();
    		if (a[i].y > maxy) maxy = a[i].y;
    		else if (a[i].y < miny) miny = a[i].y;
    	}
    	sort(a + 1, a + n + 1, cmp);
    	ans1 = a[n].x - a[1].x + max(max(maxy - a[1].y, a[1].y - miny), max(maxy - a[n].y, a[n].y - miny));
    	fo(i, 2, n - 1) ans1 = max(ans1, max(a[n].x - a[i].x, a[i].x - a[1].x) + max(maxy - a[i].y, a[i].y - miny));
    	fo(i, 1, n)
    	{
    		if (n >= 10000 && pd && a[i].x == a[i - 1].x) continue;
    		if (a[i + 1].y < a[i].y) up = 2e9, down = a[i + 1].y;
    		else up = a[i + 1].y, down = -2e9;
    		pd = 0;
    		fo(j, i + 2, n)
    		{
    			if (a[j].x - a[i].x >= ans2) {pd = 1; break;}
    			s = max(up - a[i].y, abs(up - a[j].y));
    			s1 = max(a[i].y - down, abs(down - a[j].y));
    			s = max(min(s, s1), abs(a[i].y - a[j].y));
    			ans2 = min(ans2, a[j].x - a[i].x + s);
    			if (a[j].y < a[i].y) down = max(down, a[j].y);
    			else up = min(up, a[j].y);
    		}
    	}
    	printf("%d
    %d
    ", ans1 << 1, ans2 << 1);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    用PYTHON修改电脑IP地址
    PYTHON os 模块详解
    django 笔记
    PYTHON实战目录
    群晖PLEX设置方法
    jellin docker 群晖设置方法转自先生
    PYTHON ftp 上传方法
    打包驱动EXSI
    我的PYTHON老师ALEX
    安装WHELL
  • 原文地址:https://www.cnblogs.com/jz929/p/11296199.html
Copyright © 2011-2022 走看看