HDU 6127 Hard challenge(极角排序+模拟)

本文介绍了一种在二维平面上进行动态扫描的算法,该算法通过逆时针扫描x轴并处理不同象限的点来计算最大乘积值。文章详细解释了算法思路,并分享了一些实现过程中的技巧与注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:

从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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值