bzoj 2300 动态维护上凸壳(不支持删除)

 

新技能GET。

 

用set保存点,然后只需要找前趋和后继就可以动态维护了。

 

  1 /**************************************************************
  2     Problem: 2300
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:556 ms
  7     Memory:4824 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <set>
 13 #define N 100010
 14 #define line(a,b) ((b)-(a))
 15 using namespace std;
 16  
 17 struct Job {
 18     int opt, v;
 19     double ans;
 20 };
 21 struct Vector {
 22     int x, y;
 23     void read() { scanf( "%d%d", &x, &y ); }
 24     Vector(){}
 25     Vector( int x, int y ):x(x),y(y){}
 26     Vector operator+( const Vector &b ) const { return Vector(x+b.x,y+b.y); }
 27     Vector operator-( const Vector &b ) const { return Vector(x-b.x,y-b.y); }
 28     int operator^( const Vector &b ) const { return x*b.y-y*b.x; }
 29     double len() { return sqrt(x*x+y*y); }
 30     bool operator<( const Vector &b ) const {
 31         return x<b.x || (x==b.x && y<b.y);
 32     }
 33 };
 34 typedef Vector Point;
 35  
 36 int n, m, q;
 37 Point pts[N];
 38 set<Point> cvx;
 39 Job job[N+N];
 40 bool done[N];
 41 double ans;
 42  
 43 bool onleft( const Point &a, const Point &b, const Point &c ) {
 44     return (line(a,b) ^ line(a,c)) > 0;
 45 }
 46 void insert( const Point &p ) {
 47     set<Point>::iterator prv, nxt, prev, next;
 48     prv = nxt = cvx.upper_bound( p );
 49     --prv;
 50     if( !onleft(*nxt,p,*prv) ) return;
 51     while( prv!=cvx.begin() ) {
 52         prev = prv;
 53         --prev;
 54         if( !onleft(p,*prv,*prev) ) {
 55             ans += line(*prev,*nxt).len()-line(*prev,*prv).len()-line(*prv,*nxt).len();
 56             cvx.erase(prv);
 57         } else break;
 58         prv = prev;
 59     }
 60     while( nxt!=cvx.end() ) {
 61         next = nxt;
 62         ++next;
 63         if( next==cvx.end() ) break;
 64         if( !onleft(*next,*nxt,p) ) {
 65             ans += line(*prv,*next).len()-line(*prv,*nxt).len()-line(*nxt,*next).len();
 66             cvx.erase(nxt);
 67         } else break;
 68         nxt = next;
 69     }
 70     cvx.insert( p );
 71     ans += line(*prv,p).len()+line(*nxt,p).len()-line(*prv,*nxt).len();
 72 }
 73 int main() {
 74     scanf( "%d", &n );
 75     pts[0].read();
 76     scanf( "%d", &m );
 77     for( int i=1; i<=m; i++ )
 78         pts[i].read();
 79     scanf( "%d", &q );
 80     for( int i=1; i<=q; i++ ) {
 81         scanf( "%d", &job[i].opt );
 82         if( job[i].opt==1 ) {
 83             scanf( "%d", &job[i].v );
 84             done[job[i].v] = true;
 85         }
 86     }
 87     cvx.insert( Point(0,0) );
 88     cvx.insert( pts[0] );
 89     cvx.insert( Point(n,0) );
 90     ans += line(Point(0,0),pts[0]).len() + line(Point(n,0),pts[0]).len();
 91     for( int i=1; i<=m; i++ ) 
 92         if( !done[i] ) insert( pts[i] );
 93     for( int i=q; i>=1; i-- ) {
 94         if( job[i].opt==1 ) {
 95             insert( pts[job[i].v] );
 96         } else {
 97             job[i].ans = ans;
 98         }
 99     }
100     for( int i=1; i<=q; i++ )
101         if( job[i].opt==2 )
102             printf( "%.2lf\n", job[i].ans );
103 }
View Code

 

posted @ 2015-05-27 10:38  idy002  阅读(378)  评论(0编辑  收藏  举报