• [武汉加油] bzoj 5099: [POI2018]Pionek 几何+双指针


    几何+双指针

    题目大意:现在有 (n) 个向量,请你选出来一些向量使它们的和的长度最大,输出最大值的平方。

    假如我们已经知道了最终向量的方向,我们要想使长度最大,就需要将所有投影在最终向量正方向上的向量都加起来。

    所以我们可以按角度枚举最终向量的方向,我们需要加起来的就是一段移动的区间,我们可以用双指针来维护加起来的向量。

    因为最终向量的方向有可能是给出的向量,也有可能是向量之间间隔的方向,所以每次移动指针的时候都要更新一下答案.

    因为开始给出的向量不一定有序,所以我们需要先将向量排序。

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #define LL long long
    using namespace std;
    int n;
    const double PI = acos(-1);
    LL sx, sy, ans;
    struct data
    {
    	LL x, y; double ang;
    	friend bool operator <(const data & a,const data & b) {return a.ang < b.ang;}
    }a[400010];
    int main()
    {
    	cin >> n;
    	for(int i = 1; i <= n; ++ i)scanf("%lld%lld", &a[i].x, &a[i].y), a[i].ang = atan2(a[i].y,a[i].x);
    	sort(a + 1, a + 1 + n);
    	for(int i = 1; i <= n; ++ i)a[n + i].x = a[i].x, a[n + i].y = a[i].y, a[n + i].ang = a[i].ang + 2 * PI;
    	for(int l = 1, r = 1; l <= n; ++ l)
    	{
    		while(r < n + l && a[r].ang - a[l].ang < PI)sx += a[r].x, sy += a[r].y, ans = max(ans, sx * sx + sy * sy), ++ r;
    		sx -= a[l].x, sy -= a[l].y, ans = max(ans, sx * sx + sy * sy);
    	}
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    一个 redis 异常访问引发 oom 的案例分析
    从粗放式到精益化编程
    又是一年校招
    xUtils框架的介绍(四)
    xUtils框架的介绍(三)
    hdu 4283 区间dp
    hdu 4632区间dp 回文字串计数问题
    poj 1651 区间dp
    NYOJ 石子合并(一) 区间dp入门级别
    区间dp 整数划分问题
  • 原文地址:https://www.cnblogs.com/wljss/p/12344129.html
Copyright © 2020-2023  润新知