多校7 HDU-6127 Hard challenge 几何数学,枚举极角

来源:互联网 发布:牛播最新直播室源码 编辑:程序博客网 时间:2024/05/18 14:14

原题链接:
HDU-6127

大意:
坐标系上有 n 个点,每个点带一个权值 v,两两连线,每条线的价值为两点权值的乘积,不存在两点连线经过原点。
现在从原点画出一条直线,求经过的线的值最大。

Limits:
T:5
n : 5e4
v:1e4

思路:
画一条线,一边的和为 sum1,另一边的和为 sum2 ,则经过所有线的和为 ans=sum1sum2 ,求 ans最大即可。
枚举极角,注意 角度用 atan(y/x) //double x,y;即可,用 double 记录,会发现 x=0,也是有值的..就是 PI/2

所以以后极角统一用atan(y/x) //double x,y;记录,cmp()则简单地比较角度就可完成排序。

具体见代码:(貌似可以当个模板

#include <bits/stdc++.h>using namespace std;typedef long long ll;#define mem(s,t) memset(s,t,sizeof(s))#define D(v) cout<<#v<<" "<<v<<endl#define inf 0x3f3f3f3f#define pb push_back//#define LOCALinline void read(int &x){    x=0;char p=getchar();    while(!(p<='9'&&p>='0'))p=getchar();    while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();}const int MAXN =5e4+10;const double eps=1e-9;#define  PI (acos(-1))struct A{    A(){}    A(double x,double y,int v):x(x),y(y),val(v){}    double x,y,a;    int val;}p[MAXN];bool cmp(A a,A b){return a.a<b.a;}int main() {    //freopen("1008.in","r",stdin);    //freopen("out.txt","w",stdout);    int t;    read(t);    while(t--){        int n;        ll sum=0;        read(n);        for(int i=1;i<=n;i++){            double x,y;            int val;            scanf("%lf%lf%d",&x,&y,&val);            p[i].x=x;            p[i].y=y;            p[i].val=val;            p[i].a=atan(y/x);            sum+=val;        }        sort(p+1,p+n+1,cmp);        ll sum1=0,sum2=0;        for(int i=1;i<=n;i++){            if(p[i].x>=0) sum1+=p[i].val;            else sum2+=p[i].val;        }        ll ans=sum1*sum2;        for(int i=1;i<=n;i++){            if(p[i].x>=0) sum1-=p[i].val,sum2+=p[i].val;            else sum2-=p[i].val,sum1+=p[i].val;            ans=max(ans,sum1*sum2);        }        printf("%lld\n",ans);    }}