zoukankan      html  css  js  c++  java
  • codeforces 70 D. Professor's task 动态凸包

    地址:http://codeforces.com/problemset/problem/70/D

    题目:

    D. Professor's task
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Once a walrus professor Plato asked his programming students to perform the following practical task.

    The students had to implement such a data structure that would support a convex hull on some set of points S. The input to the program had q queries of two types:

    1. Add a point with coordinates (x, y) into the set S. Note that in this case the convex hull of S could have changed, and could have remained the same.

    2. Say whether a point with coordinates (x, y) belongs to an area limited by the convex hull, including the border.

    All the students coped with the task. What about you?

    Input

    The first line contains an integer q (4 ≤ q ≤ 105).

    Then follow q lines in the following way: "t x y", where t is the query type (1 or 2), and (x, y) are the coordinates of the point ( - 106 ≤ x, y ≤ 106, x and y are integers).

    There is at least one query of type 2.

    It is guaranteed that the three queries of the first type follow first and the points given in the queries form a non-degenerative triangle. Also all the points added in S are distinct.

    Output

    For each query of the second type print one string containing "YES", if the point lies inside the convex hull or on its border. Otherwise, print "NO".

    Examples
    input
    8
    1 0 0
    1 2 0
    1 2 2
    2 1 0
    1 0 2
    2 1 1
    2 2 1
    2 20 -1
    output
    YES
    YES
    YES
    NO
    思路:动态凸包。
    摘自http://blog.csdn.net/auto_ac/article/details/10664641

    本题关键:在log(n)的复杂度内判断点在凸包 或 把点插入凸包

    判断:平衡树log(n)内选出点所属于的区域

    插入:平衡树log(n)内选出点所属于的区域, 与做一般凸包的时候类似,分别以该点向左右两边进行维护,

    一直删除不满足凸包的点,直到所有点满足凸包为止。

    水平序:

     

    可以用2个平衡树分别维护上下2个半凸包,具体实现时可以把其中一个半凸包按y轴对称以后,那么2个半凸包的维护就是同一种方法,写2个函数就ok了。

    具体平衡树可以用set或map,用STL以后边界处理有点烦,需要注意。

    水平序的凸包有一个特点(如按x排序):对于上下凸包(分开来看),x相同的点只有一个。所以用set维护比较麻烦,用map维护相对容易一点。

     

    极角序:

    之前给你的3个点一定是插入的,可以选它们的中心点o作为之后的凸包中心,按o进行极角排序。

    之后的做法就跟 “本题关键” 的做法一致。

     

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define MP make_pair
      6 #define PB push_back
      7 typedef long long LL;
      8 typedef pair<int,int> PII;
      9 const double eps=1e-8;
     10 const double pi=acos(-1.0);
     11 const int K=1e5+7;
     12 const int mod=1e9+7;
     13 
     14 
     15 
     16 /*******判断ta与tb的大小关系*******/
     17 int sgn(double ta,double tb);
     18 /** 基本几何结构 **/
     19 struct Point
     20 {
     21     double x,y,a,b;
     22     Point(double a=0, double b=0){x=a,y=b;}
     23     bool operator<(const Point &ta)const
     24     {
     25         return sgn(a,ta.a)<0||(sgn(a,ta.a)==0&&sgn(b,ta.b)<0);
     26     }
     27 };
     28 typedef set<Point>::iterator iter;
     29 double cross(Point ta,Point tb,Point tc);
     30 double getdis2(const Point &ta,const Point &tb);
     31 iter L(iter it);
     32 iter R(iter it);
     33 int q,n,ch;
     34 Point o,tmp,pt[5];
     35 set<Point>st;
     36 
     37 int main(void)
     38 {
     39     cin>>q;
     40     o.x=o.y=0;
     41     for(int i=1;i<=3;i++)
     42         scanf("%d%lf%lf",&ch,&pt[i].x,&pt[i].y),o.x+=pt[i].x,o.y+=pt[i].y;
     43     o.x/=3.0,o.y/=3.0;
     44     for(int i=1;i<=3;i++)
     45     {
     46         pt[i].a=atan2(pt[i].y-o.y,pt[i].x-o.x);
     47         pt[i].b=getdis2(o,pt[i]);
     48         st.insert(pt[i]);
     49     }
     50     set<Point>::iterator ia,ib,ic;
     51     for(int i=4;i<=q;i++)
     52     {
     53 
     54         scanf("%d%lf%lf",&ch,&tmp.x,&tmp.y);
     55         tmp.a=atan2(tmp.y-o.y,tmp.x-o.x);
     56         tmp.b=getdis2(tmp,o);
     57         ia=st.lower_bound(tmp);
     58         if(ia==st.end())ia=st.begin();
     59         ib=L(ia);
     60         if(ch==1)
     61         {
     62             if(sgn(cross(*ib,tmp,*ia),0)<=0)
     63                 continue;
     64             st.insert(tmp);
     65             ic=st.find(tmp);
     66             ia=L(ic),ib=L(ia);
     67             while(sgn(cross(*ib,*ia,*ic),0)<=0)
     68             {
     69                 st.erase(ia);
     70                 ia=ib,ib=L(ia);
     71             }
     72             ia=R(ic),ib=R(ia);
     73             while(sgn(cross(*ib,*ia,*ic),0)>=0)
     74             {
     75                 st.erase(ia);
     76                 ia=ib,ib=R(ia);
     77             }
     78         }
     79         else
     80         {
     81             if(sgn(cross(*ib,tmp,*ia),0)<=0)
     82                 printf("YES
    ");
     83             else
     84                 printf("NO
    ");
     85         }
     86     }
     87     return 0;
     88 }
     89 
     90 int sgn(double ta,double tb)
     91 {
     92     if(fabs(ta-tb)<eps)return 0;
     93     if(ta<tb)   return -1;
     94     return 1;
     95 }
     96 double cross(Point ta,Point tb,Point tc)
     97 {
     98     return (tb.x-ta.x)*(tc.y-ta.y)-(tb.y-ta.y)*(tc.x-ta.x);
     99 }
    100 double getdis2(const Point &ta,const Point &tb)
    101 {
    102     return (ta.x-tb.x)*(ta.x-tb.x)+(ta.y-tb.y)*(ta.y-tb.y);
    103 }
    104 iter L(iter it)
    105 {
    106     if(it==st.begin())it=st.end();
    107     return --it;
    108 }
    109 iter R(iter it)
    110 {
    111     if(++it==st.end()) it=st.begin();
    112     return it;
    113 }

     

  • 相关阅读:
    Java Swing3-MyDialog的基本实现
    Java IO4 实现凯撒密码加密解密文本文件
    POJ 3869 条件概率
    2017年校招全国统一模拟笔试(第三场)编程题集合
    POJ 2800 Joseph’s Problem 数论找规律
    数据结构期末考试再复习
    Java Swing2 基本登录框
    Java Swing1 基本框架
    Java 多线程1 烧水开水喝茶案例
    Java IO3 把一个图片写进txt,再写出还原图片
  • 原文地址:https://www.cnblogs.com/weeping/p/6517294.html
Copyright © 2011-2022 走看看