题意:

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

大概思路:

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

细节:

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

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

如果s覆盖,

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

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

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

查询x

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

 /**************************************************************
Problem: 3165
User: idy002
Language: C++
Result: Accepted
Time:1492 ms
Memory:4244 kb
****************************************************************/ #include <cstdio>
#include <cmath>
#include <vector>
#define lson nd<<1
#define rson nd<<1|1
#define maxn 100010
#define modx 39989
#define mody 1000000000
#define eps 1e-10
using namespace std; int sg( double x ) {
return (x>-eps)-(x<eps);
}
struct Line {
int lf, rg;
double k, b;
Line(){}
Line( int x0, int y0, int x1, int y1 ) {
lf = min( x0, x1 );
rg = max( x0, x1 );
if( x0==x1 ) {
k = 0.0;
b = max( y0, y1 );
} else {
k = (y1-y0+0.0)/(x1-x0);
b = y1-x1*k;
}
}
inline double f( int x ) {
return k*x+b;
}
inline double cx( Line &c ) {
return (c.b-b)/(k-c.k);
}
}; int n;
int ltot;
Line lns[maxn];
int v[(modx+)<<];
int wi[modx+];
double wy[modx+]; void update( int x, int i ) {
double ny = lns[i].f(x);
int s=sg(ny-wy[x]);
if( !wi[x] || (s> || (s==&&i<wi[x])) ) {
wi[x] = i;
wy[x] = ny;
}
}
void modify( int i, int nd, int lf, int rg ) {
if( lns[i].lf<=lf && rg<=lns[i].rg ) {
if( !v[nd] ) {
v[nd] = i;
return;
}
bool lu = sg( lns[i].f(lf)-lns[v[nd]].f(lf) )>;
bool ru = sg( lns[i].f(rg)-lns[v[nd]].f(rg) )>;
int mid=(lf+rg)>>;
if( lu && ru ) {
v[nd] = i;
} else if( lu || ru ) {
int lm = floor( lns[i].cx( lns[v[nd]] ) );
if( lm<=mid && lu ) {
modify( i, lson, lf, mid );
} else if( lm<=mid && ru ) {
modify( v[nd], lson, lf, mid );
v[nd] = i;
} else if( lu ) {
modify( v[nd], rson, mid+, rg );
v[nd] = i;
} else {
modify( i, rson, mid+, rg );
}
} else {
update( lf, i );
update( rg, i );
}
return;
}
int mid = (lf+rg)>>;
if( lns[i].lf<=mid ) modify( i, lson, lf, mid );
if( lns[i].rg>mid ) modify( i, rson, mid+, rg );
}
int query( int x ) {
int nd = ;
int lf = , rg = modx;
int rt = ;
double cury = -1.0;
while() {
if( v[nd] ) {
double ny = lns[v[nd]].f(x);
int s = sg( ny-cury );
if( s> || (s==&&v[nd]<rt) ) {
rt = v[nd];
cury = ny;
}
}
if( lf==rg ) break;
int mid=(lf+rg)>>;
if( x<=mid ) {
nd = lson;
rg=mid;
} else {
nd = rson;
lf=mid+;
}
}
int s = sg( wy[x]-cury );
if( s> || (s==&&wi[x]<rt) )
return wi[x];
return rt;
} int main() {
int T, lastans=;
scanf( "%d", &T );
while( T-- ) {
int opt;
scanf( "%d", &opt );
if( opt== ) {
int x;
scanf( "%d", &x );
x = ((x+lastans-)%modx+);
printf( "%d\n", lastans=query(x) );
} else {
int x0, y0, x1, y1;
scanf( "%d%d%d%d", &x0, &y0, &x1, &y1 );
x0 = (x0+lastans-)%modx+;
y0 = (y0+lastans-)%mody+;
x1 = (x1+lastans-)%modx+;
y1 = (y1+lastans-)%mody+;
lns[++ltot] = Line(x0,y0,x1,y1);
modify( ltot, , , modx );
}
}
}

bzoj 3165的更多相关文章

  1. bzoj 3165: [Heoi2013]Segment 动态凸壳

    3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 202  Solved: 89[Submit][Stat ...

  2. BZOJ.3165.[HEOI2013]Segment(李超线段树)

    BZOJ 洛谷 对于线段,依旧是存斜率即可. 表示精度误差一点都不需要管啊/托腮 就我一个人看成了mod(10^9+1)吗.. //4248kb 892ms #include <cstdio&g ...

  3. BZOJ 3165: [Heoi2013]Segment

    3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 465  Solved: 187[Submit][Sta ...

  4. Bzoj 3165 [Heoi2013]Segment题解

    3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 668  Solved: 276[Submit][Sta ...

  5. 【BZOJ 3165】【HEOI 2013】Segment

    往区间上覆盖一次函数,做法是用线段树维护标记永久化. 每次都忘了线段树要4倍空间,第一次交总是RE,再这么手残的话考场上就真的要犯逗了. #include<cstdio> #include ...

  6. BZOJ 3165 Segment

    同上题. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm&g ...

  7. 【BZOJ 3165】 [Heoi2013]Segment 李超线段树

    所谓李超线段树就是解决此题一类的问题(线段覆盖查询点最大(小)),把原本计算几何的题目变成了简单的线段树,巧妙地结合了线段树的标记永久化与标记下传,在不考虑精度误差的影响下,打法应该是这样的. #in ...

  8. bzoj 3165: [Heoi2013]Segment 线段树

    题目: Description 要求在平面直角坐标系下维护两个操作: 在平面上加入一条线段.记第i条被插入的线段的标号为i. 给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. ...

  9. BZOJ 3165 李超线段树

    思路: 李超线段树 我是把线段转成斜率的形式搞得 不知道有没有更简单的方法 //By SiriusRen #include <cmath> #include <cstdio> ...

随机推荐

  1. lintcode 40. 用栈实现队列

    使用两个栈来回倒腾可以实现队列. AC代码: import java.util.Stack; public class Queue { private Stack<Integer> sta ...

  2. Android中注册获取验证码倒计时按钮

    public class CountDownTimerUtils extends CountDownTimer { private TextView mTextView; /** * @param t ...

  3. 【shell】shell编程(五)-读取参数

    通过前几篇文章的学习,我们学会了shell的基本语法.在linux的实际操作中,我们经常看到命令会有很多参数,例如:ls -al 等等,那么这个参数是怎么处理的呢? 接下来我们就来看看shell脚本对 ...

  4. LCD之mipi DSI接口驱动调试流程【转】

    转自:http://blog.csdn.net/liwei16611/article/details/68146912 1.LCD MIPI DSI协议 MIPI-DSI是一种应用于显示技术的串行接口 ...

  5. dm368 ipnc3.0环境搭建脚本

    前言 为了方便其他人搭建dm368 ipnc3.0环境,我写了个脚本,执行脚本就可以自动搭建好环境了,绝对的傻瓜操作了,不过有一个地方让我很郁闷,那就是在用sed替换掉某段内容的时候(143行--15 ...

  6. PHP 结合实例认识 Socket

    一.简介 (本部分参考自 揭开Socket的神秘面纱 - 源码工作室) 请结合下图 Socket 抽象层的位置来理解.Socket 是应用层和 TCP/IP 协议族进行通信的中间软件抽象层,是一组接口 ...

  7. 【并行计算】基于OpenMP的并行编程

    我们目前的计算机都是基于冯偌伊曼结构的,在MIMD作为主要研究对象的系统中,分为两种类型:共享内存系统和分布式内存系统,之前我们介绍的基于MPI方式的并行计算编程是属于分布式内存系统的方式,现在我们研 ...

  8. ftp,nfs和samba的区别

    先从名字上进行理解: 1. FTP(文件传输协议) 2. NFS(网络文件系统) 3. samba 即smb(服务信息块)协议 1 其中FTP 是TCP/IP协议栈所提供的一种子协议,该子协议具体可以 ...

  9. beego学习笔记(4):开发文档阅读(4)

    beego.Run() 这个运行后, 1)解析配置文件,也就是conf目录下的. 2)判断是否开启session,并作相应的工作 3)执行用户的hookfunc. 4)是否编译模板 5)是否开启文档功 ...

  10. ISSCC 2017论文导读 Session 14 Deep Learning Processors,DNPU: An 8.1TOPS/W Reconfigurable CNN-RNN

    转载请注明,本文出自Bin的专栏http://blog.csdn.net/xbinworld,谢谢! DNPU: An 8.1TOPS/W Reconfigurable CNN-RNN Process ...