bzoj 3165

 

题意:

给出平面上一些线段,在线询问与x=x0相交的线段中,交点y最大的线段的标号,支持添加线段。

 

大概思路:

用线段树维护,线段树每个线段记录贯穿(左右端点在该区间外或上)的原线段中能覆盖其它贯穿该线段的原线段(即每个线段树线段记录贯穿该线段的所有原线段中“最高”的)

细节:

添加原线段s到线段树线段nd:

如果s不能覆盖,根据s的大小传递到左儿子或右儿子或都传

如果s覆盖,

        如果原本没有线段,则直接设置为s

   如果有线段ss,求s与ss的交点,将短(比较x上投影的长度)的线段“压”到交点所在儿子,长的变成本区间的。

  (要注意如果y相等,比较标号)

查询x

  查询覆盖x的所有区间的线段树线段对应的原线段(有的话)中在x处y最大的。

 

  1 /**************************************************************
  2     Problem: 3165
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:1492 ms
  7     Memory:4244 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <vector>
 13 #define lson nd<<1
 14 #define rson nd<<1|1
 15 #define maxn 100010
 16 #define modx 39989
 17 #define mody 1000000000
 18 #define eps 1e-10
 19 using namespace std;
 20  
 21 int sg( double x ) {
 22     return (x>-eps)-(x<eps);
 23 }
 24 struct Line {
 25     int lf, rg;
 26     double k, b;
 27     Line(){}
 28     Line( int x0, int y0, int x1, int y1 ) {
 29         lf = min( x0, x1 );
 30         rg = max( x0, x1 );
 31         if( x0==x1 ) {
 32             k = 0.0;
 33             b = max( y0, y1 );
 34         } else {
 35             k = (y1-y0+0.0)/(x1-x0);
 36             b = y1-x1*k;
 37         }
 38     }
 39     inline double f( int x ) {
 40         return k*x+b;
 41     }
 42     inline double cx( Line &c ) {
 43         return (c.b-b)/(k-c.k);
 44     }
 45 };
 46  
 47 int n;
 48 int ltot;
 49 Line lns[maxn];
 50 int v[(modx+10)<<2];
 51 int wi[modx+10];
 52 double wy[modx+10];
 53  
 54 void update( int x, int i ) {
 55     double ny = lns[i].f(x);
 56     int s=sg(ny-wy[x]);
 57     if( !wi[x] || (s>0 || (s==0&&i<wi[x])) ) {
 58         wi[x] = i;
 59         wy[x] = ny;
 60     }
 61 }
 62 void modify( int i, int nd, int lf, int rg ) {
 63     if( lns[i].lf<=lf && rg<=lns[i].rg ) {
 64         if( !v[nd] ) {
 65             v[nd] = i;
 66             return;
 67         }
 68         bool lu = sg( lns[i].f(lf)-lns[v[nd]].f(lf) )>0;
 69         bool ru = sg( lns[i].f(rg)-lns[v[nd]].f(rg) )>0;
 70         int mid=(lf+rg)>>1;
 71         if( lu && ru ) {
 72             v[nd] = i;
 73         } else if( lu || ru ) {
 74             int lm = floor( lns[i].cx( lns[v[nd]] ) );
 75             if( lm<=mid && lu ) {
 76                 modify( i, lson, lf, mid );
 77             } else if( lm<=mid && ru ) {
 78                 modify( v[nd], lson, lf, mid );
 79                 v[nd] = i;
 80             } else if( lu ) {
 81                 modify( v[nd], rson, mid+1, rg );
 82                 v[nd] = i;
 83             } else {
 84                 modify( i, rson, mid+1, rg );
 85             }
 86         } else {
 87             update( lf, i );
 88             update( rg, i );
 89         }
 90         return;
 91     }
 92     int mid = (lf+rg)>>1;
 93     if( lns[i].lf<=mid ) modify( i, lson, lf, mid );
 94     if( lns[i].rg>mid ) modify( i, rson, mid+1, rg );
 95 }
 96 int query( int x ) {
 97     int nd = 1;
 98     int lf = 1, rg = modx;
 99     int rt = 0;
100     double cury = -1.0;
101     while(1) {
102         if( v[nd] ) {
103             double ny = lns[v[nd]].f(x);
104             int s = sg( ny-cury );
105             if( s>0 || (s==0&&v[nd]<rt) ) {
106                 rt = v[nd];
107                 cury = ny;
108             }
109         }
110         if( lf==rg ) break;
111         int mid=(lf+rg)>>1;
112         if( x<=mid ) {
113             nd = lson;
114             rg=mid;
115         } else {
116             nd = rson;
117             lf=mid+1;
118         }
119     }
120     int s = sg( wy[x]-cury );
121     if( s>0 || (s==0&&wi[x]<rt) )
122         return wi[x];
123     return rt;
124 }
125  
126 int main() {
127     int T, lastans=0;
128     scanf( "%d", &T );
129     while( T-- ) {
130         int opt;
131         scanf( "%d", &opt );
132         if( opt==0 ) {
133             int x;
134             scanf( "%d", &x );
135             x = ((x+lastans-1)%modx+1);
136             printf( "%d\n", lastans=query(x) );
137         } else {
138             int x0, y0, x1, y1;
139             scanf( "%d%d%d%d", &x0, &y0, &x1, &y1 );
140             x0 = (x0+lastans-1)%modx+1;
141             y0 = (y0+lastans-1)%mody+1;
142             x1 = (x1+lastans-1)%modx+1;
143             y1 = (y1+lastans-1)%mody+1;
144             lns[++ltot] = Line(x0,y0,x1,y1);
145             modify( ltot, 1, 1, modx );
146         }
147     }
148 }
View Code

 

posted @ 2015-03-05 15:28  idy002  阅读(644)  评论(0编辑  收藏  举报