hdu6127-(数学+暴力)

题解:枚举每一个点假设这个点和原点连成线后,这条线左边的点的总值为a,右边的点的总值为b,这个点的值为v那么这个点的最大值ans = max((a+v)*b,(b+v)*a);
然后求出所有的点中最大值即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int mx = 5e4+5;
const double inf =  0x3f3f3f3f3f;
typedef long long int ll;
struct point{
    ll x,y,v;
    double xie;
    bool operator<(const point &a)const{
        return xie<a.xie;
    }
};
vector<point>v[4];
int len[4];
point x1,y1;
ll getans(int x,ll a,ll b,int pos,int now){
    int k = lower_bound(v[pos].begin(),v[pos].end(),v[now][x])-v[pos].begin();
    ll cnt = v[now][len[now]].v;
    if(k==0)
        b += v[pos][len[pos]].v;
    else if(k == len[pos]+1)
        a += v[pos][len[pos]].v;
    else{
        a += v[pos][k-1].v;
        b += v[pos][len[pos]].v-v[pos][k-1].v;
    }
    if(now == 0){
        if(x1.y>0)
            a+=x1.v;
        else
            b+=x1.v;
        if(y1.x<0)
            a+=y1.v;
        else
            b+=y1.v;
    }
    else if(now == 1){
        if(x1.y<0)
            a+=x1.v;
        else
            b+=x1.v;
        if(y1.x<0)
            a+=x1.v;
        else
            b+=x1.v;
    }
    else if(now == 2){
        if(x1.y>0)
            b+=x1.v;
        else
            a+=x1.v;
        if(y1.x>0)
            a+=x1.v;
        else
            b+=x1.v;
    }
    else if(now == 3){
        if(x1.y>0)
            a+=x1.v;
        else
            b+=x1.v;
        if(y1.x>0)
            a+=y1.v;
        else
            b+=y1.v;
    }
    ll ans = (a+cnt-v[now][x].v)*(b+v[now][x].v);
    if(x==0)
        ans = max(ans,(a+cnt)*b);
    else
        ans = max(ans,(a+cnt-v[now][x-1].v)*(b+v[now][x-1].v));
    return ans;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        point x;
        for(int i = 0; i < 4; i++)
            v[i].clear();
        v[0].push_back({0,0,0,0});
        v[2].push_back({0,0,0,0});
        v[1].push_back({0,0,0,inf});
        v[3].push_back({0,0,0,inf});
        x1.y = y1.x = x1.v = y1.v = 0;
        for(int i = 0; i < n; i++){
            scanf("%I64d%I64d%I64d",&x.x,&x.y,&x.v);
           // cout<<x.x<<x.y<<x.v<<endl;
            if(x.x==0)
                x1 = x;
            else if(x.y==0)
                y1 = x;
            else{
                x.xie = 1.0*x.y/x.x;
                if(x.x>0&&x.y>0)
                    v[0].push_back(x);
                else if(x.x<0&&x.y>0)
                    v[1].push_back(x);
                else if(x.x<0&&x.y<0)
                    v[2].push_back(x);
                else
                    v[3].push_back(x);
            }
        }
        for(int i = 0; i < 4; i++){
            sort(v[i].begin(),v[i].end());
            len[i] = v[i].size()-1;
            for(int j = 1; j <= len[i]; j++)
                v[i][j].v += v[i][j-1].v;
        }
        ll ans = 0;
        if(x1.y !=0){
            ll sum1 = v[0][v[0].size()-1].v+(y1.x>0?y1.v:0)+v[1][v[1].size()-1].v;
            ll sum2 = v[3][v[3].size()-1].v+(y1.x<0?y1.v:0)+v[2][v[2].size()-1].v;
            ans = max((sum1+x1.v)*sum2,(sum2+x1.v)*sum1);
        }
        if(y1.x !=0){
            ll sum1 = v[0][v[0].size()-1].v+(x1.y>0?x1.v:0)+v[3][v[3].size()-1].v;
            ll sum2 = v[1][v[1].size()-1].v+(x1.y<0?x1.v:0)+v[2][v[2].size()-1].v;
            ans = max(ans,max((sum1+x1.v)*sum2,(sum2+x1.v)*sum1));
        }
        for(int i = 1; i < v[0].size(); i++) ans = max(ans,getans(i,v[1][len[1]].v,v[3][len[3]].v,2,0));
        for(int i = 1; i < v[1].size(); i++) ans = max(ans,getans(i,v[2][len[2]].v,v[0][len[0]].v,3,1));
        for(int i = 1; i < v[2].size(); i++) ans = max(ans,getans(i,v[3][len[3]].v,v[1][len[1]].v,0,2));
        for(int i = 1; i < v[3].size(); i++) ans = max(ans,getans(i,v[0][len[0]].v,v[2][len[2]].v,1,3));
        printf("%I64d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值