思路:
从x轴这条直线逆时针扫一遍,对于每个点的改变我们可以o(1)的算出改变后的value,所以整体o(n)。
小技巧?
我是把第三象限的映射到了第一象限,第四象限映射到了第二象限做的,因为在扫的过程中会同时影响这两个象限的点,但是对于不同象限的点,所改变的集合不同,所以这么考虑。
坑点:
注意用long lont int;
double的话,会迷之误差1。wa到死。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<map>
#include<algorithm>
#include<cmath>
//#define inf 0x3f3f3f3f
#define inf 1e15
#define eps 1e-6
typedef long long int lli;
using namespace std;
const int maxn = 5e4+20;
struct poi{
double x,y,v,p;
poi(){}
poi(double xx,double yy,double vv,double pp){x=xx,y=yy,v=vv,p=pp;}
//poi operator - (poi t){return poi(x-t.x,y-t.y,0,0);}
double operator * (poi t){return x*t.y-y*t.x;}
}a13[maxn],a24[maxn];
bool cmp(poi a,poi b){
return a*b > 0;
}
int main(){
// freopen("1008.in","r",stdin);
// freopen("my.out","w",stdout);
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
double x,y;lli v;
int cnt13 = 0,cnt24 = 0;
lli vs = 0,vx = 0;
for(int i = 1;i <= n;i++){
scanf("%lf%lf%lld",&x,&y,&v);
if(y>=0)
vs += v;
else
vx += v;
if(x >= 0 && y >= 0){
a13[cnt13++] = poi(x,y,v,1);
}
else if(x>= 0 && y < 0){
a24[cnt24++] = poi(-x,-y,v,4);
}
else if(x <= 0 && y>=0){
a24[cnt24++] = poi(x,y,v,2);
}
else{
a13[cnt13++] = poi(-x,-y,v,3);
}
}
sort(a13,a13+cnt13,cmp);
sort(a24,a24+cnt24,cmp);
lli ans = vs*vx;
for(int i = 0;i < cnt13;i++){
if(a13[i].p==1){
vx += a13[i].v;vs -= a13[i].v;
ans = max(ans,vx*vs);
}
else{
vs += a13[i].v;vx -= a13[i].v;
ans = max(ans,vx*vs);
}
}
for(int i = 0;i < cnt24;i++){
if(a24[i].p==2){
vx += a24[i].v;vs -= a24[i].v;
ans = max(ans,vx*vs);
}
else{
vs += a24[i].v;vx -= a24[i].v;
ans = max(ans,vx*vs);
}
}
printf("%lld\n",ans);
}
return 0;
}