-
題目大意
平面上有n個點,每個點有一個價值,每兩個點之間都有一條線段,定義線段的值爲兩個點價值的乘積,現在讓你找一條過原點的直線(直線不經過任何一個節點),將這條直線所經過的所有線段的值求和,問最大的和是多少.
-
分析
我們容易知道如果確定了直線的位置,那麼將直線兩邊的點分別求和再乘起來就是答案
那麼現在只需要枚舉直線的位置即可,只有當直線掃過點的時候值纔會發生變化,所以我們離散化地取枚舉每個節點,在跨過節點的時候只需要O(1)的複雜度就能對答案進行更新。
-
代碼
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;
#define LL long long int
const double pi=4*atan(1.0);
const int MAXN=50009;
int T;
int n;
LL sum_up,sum_down;
struct Node
{
int x,y,v;
double r;
bool is_up;//1表示在x軸上面
}node[MAXN];
double Get_r(int x,int y)//給定一個點的座標,如果這個點在x軸上方,返回這個點和原點連線與軸正方向的夾角。如果這個點在x軸下方,返回這個點和原點連線與軸負方向的夾角
{
if(x==0)return pi;
if(y==0)return 0;
if(x<0 && y>0)return pi-atan(-(double)y/(double)x);
if(x>0 && y<0)return pi-atan(-(double)y/(double)x);
return atan((double)y/(double)x);
}
bool Get_up(int x,int y)//判斷一個節點在x軸上方還是下方,在x軸上的點正方向歸爲下方,負方向歸爲上方
{
if(y>0)return 1;
else if(y<0)return 0;
else
{
if(x<0)return 1;
else return 0;
}
}
bool cmp(Node a,Node b)
{
return a.r < b.r;
}
void In()
{
sum_up=sum_down=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].v);
if(node[i].x==0 && node[i].y==0)node[i].v=0;
node[i].r=Get_r(node[i].x,node[i].y);
node[i].is_up=Get_up(node[i].x,node[i].y);
if(node[i].is_up==1)sum_up+=node[i].v;
else sum_down+=node[i].v;
}
}
LL Work()
{
LL ans=sum_up*sum_down;
double cur_r=0;
int i=1;
while(node[i].r==0)i++;
while(i<=n)
{
cur_r=node[i].r;
while(node[i].r==cur_r)
{
if(node[i].is_up==1)
{
sum_up-=node[i].v;
sum_down+=node[i].v;
}
else
{
sum_up+=node[i].v;
sum_down-=node[i].v;
}
i++;
}
ans=max(ans,sum_down*sum_up);
}
return ans;
}
void Test()
{
cout<<"sum_up="<<sum_up<<",sum_down="<<sum_down<<endl;
for(int i=1;i<=n;i++)cout<<node[i].is_up<<" ";
cout<<endl;
}
int main()
{
scanf("%d",&T);
while(T--)
{
In();
//Test();
sort(node+1,node+n+1,cmp);
cout<<Work()<<endl;
}
}
/*
2
2
1 1 1
1 -1 1
3
1 1 1
1 -1 10
-1 0 100
1
4
1 0 4
0 1 5
0 -1 3
-2 0 6
*/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122