zoukankan      html  css  js  c++  java
  • 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
    ", 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
  • 相关阅读:
    压缩和还原压缩的JS代码
    mysql给某字段随机赋特定范围的整数值
    (五)绘制图像
    (四)旋转 缩放 位移 保存状态
    (三)描边 填充 绘制 开始路径 结束路径 绘制文本
    (二)导出图像
    (一)获取上下文绘图环境
    封装原生Ajax
    原生Ajax写法(GET)
    Angular跨域
  • 原文地址:https://www.cnblogs.com/idy002/p/4315959.html
Copyright © 2011-2022 走看看