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\n",ans);
83     }
84     return 0;
85 }

 

posted @ 2017-08-15 21:00  Kayden_Cheung  阅读(206)  评论(0编辑  收藏  举报
//目录