zoukankan      html  css  js  c++  java
  • HDU 6127 Hard challenge(扫描线)

    http://acm.hdu.edu.cn/showproblem.php?pid=6127

    题意:

    有n个点,每个点有一个$(x,y)$坐标和一个权值,任意两点之间都有连线,并且连线的权值为两个顶点的。现在画一条直线,求穿过的直线的权值和最大为多少。

     

    思路:

    直线将这些点分成了两个部分,然后你可以发现这两个部分之间所有直线的权值和为他们各部分的权值和的乘积。然后我们将所有点按极角排序,预处理一个前缀和,然后用扫描线扫描一圈即可。

    我的做法是每次扫描一下点的个数,然后利用前缀和去计算。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<sstream>
     6 #include<vector>
     7 #include<stack>
     8 #include<queue>
     9 #include<cmath>
    10 #include<map>
    11 #include<set>
    12 using namespace std;
    13 
    14 #define MAXN 50005
    15 #define LL long long
    16 
    17 struct Point
    18 {
    19     LL x,y;
    20     int v;
    21     double rad;
    22     bool operator < (const Point&rhs) const
    23     {
    24         return rad < rhs.rad;
    25     }
    26 }p[MAXN];
    27 
    28 LL sum[MAXN];
    29 
    30 bool left(Point a, Point b)
    31 {
    32      return (LL)a.x*b.y - (LL)a.y*b.x >= 0;
    33 }
    34 
    35 int main()
    36 {
    37     int n,m,T;
    38     //freopen("in.txt","r",stdin);
    39     scanf("%d",&T);
    40     while(T--)
    41     {
    42         scanf("%d",&n);
    43         for(int i=0;i<n;i++)
    44         {
    45             scanf("%I64d%I64d%d",&p[i].x,&p[i].y,&p[i].v);
    46             p[i].rad = atan2(p[i].y, p[i].x);
    47         }
    48         sort(p,p+n);
    49         sum[0]=p[0].v;
    50         for(int i=1;i<n;i++)  sum[i]=sum[i-1]+p[i].v;
    51 
    52         LL ans=0;
    53         LL  L = 0, R = 0, cnt=0;
    54         while (L < n)   //每个点都尝试与原点成为分割线
    55         {
    56             if (R == L)  { R = (R + 1) % n; cnt++; }  //空区域,数量+1,后面还会减去的
    57             while (R != L && left(p[L], p[R]))   //R不等于L并且在180度之内
    58             {
    59                 R = (R + 1) % n;
    60                 cnt++;
    61             }
    62 
    63             cnt--; //分隔线旋转,原本在分隔线上的点到了右边,所以要减去
    64                    //可以理解为将该点分在分隔线的下方
    65 
    66             LL t1,t2;
    67             int num=L+cnt;
    68             if(num<n)
    69             {
    70                 t1=sum[num]-sum[L];
    71                 t2=sum[n-1]-t1;
    72                 ans=max(ans,t1*t2);
    73             }
    74             else
    75             {
    76                 t1=sum[n-1]-sum[L]+sum[num-(n-1)-1];
    77                 t2=sum[n-1]-t1;
    78                 ans=max(ans,t1*t2);
    79             }
    80             L++;   //分隔线旋转
    81         }
    82         printf("%I64d
    ",ans);
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    java优雅的使用elasticsearch api
    springboot mybatis优雅的添加多数据源
    java通过shield链接Elasticsearch
    java spark-streaming接收TCP/Kafka数据
    hiveQL求差集
    hiveQL去重
    Ubuntu16.04+Opencv3.3的安装教程
    TensorFlow池化层-函数
    TensorFlow激活函数+归一化-函数
    TensorFlow图像预处理-函数
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7367728.html
Copyright © 2011-2022 走看看