传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6127
Hard challenge
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 633 Accepted Submission(s): 249
For each test case:
The first line contains a positive integer n(1≤n≤5×104) .
The next n lines, the i th line contains three integers xi,yi,vali(|xi|,|yi|≤109,1≤vali≤104) .
A single line contains a nonnegative integer, denoting the answer.
2 2 1 1 1 1 -1 1 3 1 1 1 1 -1 10 -1 0 100
1 1100
平面直角坐标系上有n个整点,第i个点有一个点权vali,坐标为(xi,yi),其中不存在任意两点连成的直线经过原点
整点两两之间连有一条线段,线段的权值为其两端点的权值之积。你需要作一条过原点而不过任意一个给定整点的
直线,使得和这条直线相交的线段的权值和最大。
1≤n≤5×104,1≤vali≤104,∣xi∣,∣yi∣≤109。
对于一条直线,线段权值和实际上就等于其两边点权和的乘积,所以把所有点按极角排个序,然后扫一圈就好了。
感觉这个题目的数据是有点水的,很多情况并没有涉及到就能过。比如,经过原点的一条直线上的两个点应该
必须被一条直线分成两在两侧的,而在一侧充计是不对的。还有就是关于原点的话它的权值是不应该被计入的。
也没有精度问题。再就是LL的问题要注意了。解释一下:比如‘左边’权值和为L,‘右边’权值和为R,(先按着y轴为
直线分的,注意y轴的点关于x轴上下点不会在一个区域内的)当扫描一个点的时候,那在该点与原点连线上的所有
都会变动,对于一个点a而言,如果本身在左边,那么要变到右边的话,L-=a.val,R+=a.val。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
struct node
{
LL x,y;
LL val;
double k;
}point[5*10100];
double get_k(LL x,LL y)
{
if(x==0)return -2*atan(1.0);
return atan((double)y/(double)x);
}
bool Dir(LL x,LL y)
{
if(x==0)
{
if(y>0)return true;
else return false;
}
if(x>0)return false;
return true;
}
bool cmp(node a,node b)
{
return a.k<b.k;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
LL L=0,R=0,num=0;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&point[i].x,&point[i].y,&point[i].val);
//if(point[i].x==point[i].y&&point[i].x==0)point[i].val=0;
point[i].k=get_k(point[i].x,point[i].y);
if(Dir(point[i].x,point[i].y))L+=point[i].val;
else R+=point[i].val;
}
sort(point+1,point+1+n,cmp);
num=L*R;
for(int i=1;i<=n;)
{
double kk=point[i].k;
while(point[i].k==kk)
{
if(point[i].x==0)
{
if(point[i].y>0)
{
L-=point[i].val;
R+=point[i].val;
}
else
{
R-=point[i].val;
L-=point[i].val;
}
}
else if(point[i].x>0)
{
R-=point[i].val;
L+=point[i].val;
}
else
{
R+=point[i].val;
L-=point[i].val;
}
i++;
}
num=max(num,L*R);
}
printf("%lld\n",num);
}
return 0;
}