码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-22 09:48:59      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:++   更新   +=   can   ret   之间   long   str   fine   

几何+双指针

题目大意:现在有 \(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;
}

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

标签:++   更新   +=   can   ret   之间   long   str   fine   

原文地址:https://www.cnblogs.com/wljss/p/12344129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!