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 }