【模板】凸包
今天遇到一个题,有两种操作,A添加新顶点,B,询问某个点是否在当前点的凸包内。。简单来说就是只有添加操作的凸包维护,做法也不难想,可以从我们正常的水平序求凸包中得到启发,即动态维护一条上凸折线,以及一条下凸折线,用STL可以得到一个O(nlogn)的做法。。切完顺便把程序当场模板留了下来,感觉这个思路用来做模板挺好用的,不停的insert操作就可以了。代码也短
View Code
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 #define mp(x,y) make_pair(x,y) 6 #define foreach(i,n) for(__typeof(n.begin()) i = n.begin(); i!=n.end(); i++) 7 #define X first 8 #define Y second 9 using namespace std; 10 typedef long long LL; 11 typedef pair<int,int> pii; 12 13 map<int,int> up[2]; 14 map<int,int>::iterator iter,p,q; 15 16 int strcmp( pii a, pii b, pii c){ 17 LL ret = ((LL)b.X-a.X)*((LL)c.Y-a.Y)-((LL)b.Y-a.Y)*((LL)c.X-a.X); 18 return ret>0?1:(ret==0?0:-1); 19 } 20 21 bool pan( map<int,int> &g ,int x,int y){ 22 if ( g.size() == 0 ) return false; 23 if ( g.find(x) != g.end() ) return y>=g[x]; 24 if ( g.begin()->X > x || (--g.end())->X < x ) return false; 25 iter = g.lower_bound(x); 26 p = q = iter; 27 p--; 28 return strcmp(*p,*q,mp(x,y))>=0; 29 } 30 31 void insert( map<int,int> &g, int x,int y){ 32 if ( pan(g,x,y) ) return; 33 g[x] = y; 34 iter = g.find(x); 35 while ( iter != g.begin() ){ 36 p = iter; 37 p--; 38 if ( p == g.begin() ) break; 39 q = p; 40 q--; 41 if ( strcmp(*q,*iter,*p)>=0 ) g.erase(p); 42 else break; 43 } 44 iter = g.find(x); 45 while ( true ){ 46 p = iter; 47 p++; 48 if ( p == g.end() ) break; 49 q = p; 50 q++; 51 if ( q == g.end() ) break; 52 if ( strcmp(*iter,*q,*p)>=0 ) g.erase(p); 53 else break; 54 } 55 } 56 int main(){ 57 int cas; 58 scanf("%d", &cas ); 59 while ( cas -- ){ 60 int k,x,y 61 scanf("%d%d%d", &k, &x, &y ); 62 if ( k == 1 ) 63 insert( up[0], x,y ), 64 insert( up[1], x,-y); 65 else 66 printf( pan(up[0],x,y)&&pan(up[1],x,-y)?"YES\n":"NO\n" ); 67 } 68 return 0; 69 }