HDU
来源:互联网 发布:windows解压war包 编辑:程序博客网 时间:2024/06/07 05:21
题目大意:
多组测试数据(t<=5),每组给你平面直角坐标系上的 n 个(1<=n<=5e4)。这n个点两两之间有一条连线,连线值为这两点的值的乘积。现在让你选一条过原点的直线,使得经过直线的线段的值的和最大。
分析:
直线绕原点旋转,尺取每个点和原点的连线和 x 轴正方向的夹角(0~2π)。即:尺取每个点进入直线上区域或下区域。
未AC代码:
#include<bits/stdc++.h>#define maxn 50050using namespace std;int n;double small=1e-7;double p=4*atan(1.0);struct point{ int x;int y; double ang; long long int v;}a[maxn];double Get_ang(int x,int y){ double t=(double)(y)/(double)(x); if(x>0&&y>0)return atan(t); if(x<0&&y>0)return p-atan(-t); if(x<0&&y<0)return p+atan(t); if(x>0&&y<0)return 2*p-atan(-t); if(y==0) { if(x>0)return 0; else return p; } if(x==0) { if(y>0)return p/2; else return 3*p/2; }}bool cmp(point a,point b){ return a.ang<b.ang;}int main(){ int t; scanf("%d",&t); while(t--) { scanf("%d",&n); long long int up=0,down=0,temp_v; int num=0,temp_x,temp_y; for(int i=0;i<n;i++) { scanf("%d%d%lld",&temp_x,&temp_y,&temp_v); if(temp_x==0&&temp_y==0)continue; a[num].x=temp_x; a[num].y=temp_y; a[num].v=temp_v; a[num].ang=Get_ang(a[num].x,a[num].y); if(a[num].y>0||(a[num].y==0&&a[num].x>0))//x轴正方向上得点在up,x轴负方向上的点在down。 { up+=a[i].v; } else { down+=a[i].v; } num++; } //printf("%lld %lld\n",up,down); sort(a,a+num,cmp); long long int ans=down*up; n=num; int j=0; for(int i=0;i<n;i++) { if(a[i].ang>p-small) { j=i; break; } } int i=0; while(1)//每次循环计算第i个在下面,第j个在上面的值 { if(i>=n||abs(a[i].ang-p)<small)break; up-=a[i].v;down+=a[i].v; while(1) { if(i>=n||a[i+1].ang-a[i].ang>small)break; i++; up-=a[i].v;down+=a[i].v; } while(1) { if(j>=n||a[j].ang>a[i].ang+p+small)break; up+=a[j].v;down-=a[j].v; j++; } j--; ans=max(ans,up*down); } while(1)//每次循环计算第i个在下面,第j个在上面的值.2 { if(i>=n)break; up-=a[i].v;down+=a[i].v; while(1) { if(i>=n||a[i+1].ang-a[i].ang>small)break; i++; up-=a[i].v;down+=a[i].v; } if(i>=n)i=n-1; j=max(j,i+1); while(1) { if(j>=n||a[j].ang>a[i].ang-p+small&&j<i)break; up+=a[j].v;down-=a[j].v; j++; j%=n; } j--; ans=max(ans,up*down); } /* for(int i=0;i<n-1;i++) { up-=a[i].v; down+=a[i].v; if(a[i+1].ang>p-small) { j%=n; while(1) { if(a[j].ang>a[i+1].ang-p-small)break; up+=a[j].v; down-=a[j].v; j++; j%=n; } } else while(1) { if(a[j].ang>p+a[i+1].ang-small)break; up+=a[j].v; down-=a[j].v; j++; j%=n; } printf("%lld %lld\n",up,down); ans=max(ans,up*down); //printf("%lld",ans); }*/ printf("%lld\n",ans); }}
边界问题。