题目链接:点击打开链接
题解思路:很简单,每次选取一个点,让原点与此点连接然后再使他偏离一点点,那么这个线就将点分为左右两边,ans就可以更新 ans = max(ans,v*max(l,r)+l*r);),v是此点的值,l,r分别表示两部分各自的和,先将点分为四个象限,各个象限按斜率从小到大排序,比如当枚举到第一象限时,两部分的其中一个部分应该是第二象限+此点在第一象限斜率递增部分的点+第三象限递减的部分,其他类似。
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#define inf 0x3f3f3f3f
using namespace std;
const int mx = 2e3+10;
typedef long long ll;
int n,m;
ll to[4];
struct node{
int x,y;
int v;
node(){}
node(int xx,int yy,int vv): x(xx),y(yy),v(vv){}
bool operator < (node A)const{
return 1.0*y/x < 1.0*A.y/A.x;
}
}s1,s2;
vector<node> vec[4];
vector<ll>val[4];
ll get_data(ll t,ll s,node no,int p,int p1){
int it = lower_bound(vec[p].begin(),vec[p].end(),no)-vec[p].begin();
int ip = lower_bound(vec[p1].begin(),vec[p1].end(),no)-vec[p1].begin();
ll l = (t + to[p] - val[p][it+1] + val[p1][ip]);
ll r = (s + val[p][it] + to[p1] - val[p1][ip]);
if(s1.y>0&&(p==0||p==3)) l += s1.v;
else if(s1.y<0||(p==1||p==2)) l += s1.v;
else r += s1.v;
if(s2.x>0&&(p==2||p==3)) r += s2.v;
else if(s2.x<0&&(p==0||p==1)) r += s2.v;
else l += s2.v;
return no.v*max(l,r)+l*r;
}
int main(){
int t;
scanf("%d",&t);
int a,b,c;
while(t--){
scanf("%d",&n);
for(int i=0;i<4;i++) vec[i].clear(),val[i].clear();
s1.v = s2.v = 0;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);
if(a==0) s1 = node(a,b,c);
else if(b==0) s2 = node(a,b,c);
else if(a>0&&b>0) vec[0].push_back(node(a,b,c));
else if(a<0&&b>0) vec[1].push_back(node(a,b,c));
else if(a<0&&b<0) vec[2].push_back(node(a,b,c));
else vec[3].push_back(node(a,b,c));
}
for(int i=0;i<4;i++){
sort(vec[i].begin(),vec[i].end());
ll sum = 0;
val[i].push_back(0);
for(int j=0;j<vec[i].size();j++){
sum += vec[i][j].v;
val[i].push_back(sum);
}
}
ll ans = 0;
for(int i=0;i<4;i++) to[i] = val[i].back();
ll l = to[0]+to[3],r = to[1]+to[2];
if(s2.x>0) l += s2.v;
else r += s2.v;
ans = max(ans,s1.v*max(l,r)+l*r);
l = to[0]+to[1], r = to[2]+to[3];
if(s1.y>0) l += s1.v;
else r += s2.v;
ans = max(ans,s1.v*max(l,r)+l*r);
for(int i=0;i<vec[0].size();i++) ans = max(ans,get_data(to[1],to[3],vec[0][i],0,2));
for(int i=0;i<vec[1].size();i++) ans = max(ans,get_data(to[2],to[0],vec[1][i],1,3));
for(int i=0;i<vec[2].size();i++) ans = max(ans,get_data(to[3],to[1],vec[2][i],2,0));
for(int i=0;i<vec[3].size();i++) ans = max(ans,get_data(to[0],to[2],vec[3][i],3,1));
printf("%lld\n",ans);
}
return 0;
}