P4097 [HEOI2013]Segment

题目描述

要求在平面直角坐标系下维护两个操作:

  1. 在平面上加入一条线段。记第 \(i\) 条被插入的线段的标号为 \(i\)
  2. 给定一个数 \(k\),询问与直线 \(x = k\) 相交的线段中,交点最靠上的线段的编号。

输入输出格式

输入格式:

第一行一个整数 \(n\),表示共 \(n\) 个操作

接下来 \(n\) 行,每行第一个数为 \(0\) 或 \(1\)

若该数为 \(0\),则后面跟着一个正整数 \(k\),表示询问与直线 \(x = ((k + lastans – 1)\%39989+1)\)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中\(\%\)表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段 \(y\) 坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号

若该数为 \(1\),则后面跟着四个正整数 \(x_0, y_0, x_1, y_1\),表示插入一条两个端点为 \(((x_0+lastans-1)\%39989+1\),\((y_0+lastans-1)%10^9+1)\)和 \(((x_1+lastans-1)%39989+1,(y1+lastans-1)\%10^9+1)\) 的线段

其中 \(lastans\) 为上一次询问的答案。初始时 \(lastans=0\)

输出格式:

对于每个 \(0\) 操作,输出一行,包含一个正整数,表示交点最靠上的线段的编 号。若不存在与直线相交的线段,答案为 \(0\)

说明

对于\(30\%\)的数据,\(n ≤ 1000\)

对于\(100\%\)的数据,\(1 ≤ n ≤ 10^5, 1 ≤ k, x_0, x_1 ≤ 39989, 1 ≤ y_0 ≤ y_1 ≤ 10^9\)


李超线段树

对\(x\)建线段树,每个区间存一个线段进行标记永久化。

这个线段用斜截式子\(k,b\)保存

当查询时,遍历的时候拿所有的节点进行更新。

当修改时,当完全覆盖当前区间时

  • 如果这个区间还没有线段,占上去

  • 如果这个区间上的线段和当前线段在此段无交点,选择上面的一个保留

  • 判断交点在\(mid\)左边还是右边

    • 以在左边为例

      如果当前左端点>区间左端点,当前区间保留,自己进左儿子去更新

      否则把自己留着这,把当前区间的踹下去

    • 右边同理

因为每个线段最多被划分成\(\log n\)段,所以复杂度是\(O(n\log^2 n)\)的


Code:

#include <cstdio>
#include <algorithm>
#include <cmath>
using std::max;
const int N=1e5+10;
int n=39989,m;
struct seg
{
double k,b;
int id;
seg(){}
seg(int x,int y,int xx,int yy,int Id)
{
k=1.0*(yy-y)/(1.0*(xx-x));
b=y-k*x;
id=Id;
}
double pos(double x){return k*x+b;}
}mx[N<<2];
const double eps=1e-5;
bool dcmp(double x,double y){return fabs(x-y)<eps;}
struct beecute
{
int id;double mx;
beecute(){}
beecute(int Id,double Mx){id=Id,mx=Mx;}
bool friend operator <(beecute a,beecute b){return dcmp(a.mx,b.mx)?a.id>b.id:a.mx<b.mx;}
}bee[N],las;
#define ls id<<1
#define rs id<<1|1
void change(int id,int L,int R,int l,int r,seg ins)
{
int Mid=L+R>>1;
if(l==L&&r==R)
{
if(!mx[id].id) {mx[id]=ins;return;}
double a=ins.pos(1.0*l),b=ins.pos(1.0*r),c=mx[id].pos(1.0*l),d=mx[id].pos(1.0*r);
if(a>c&&b>d) {mx[id]=ins;return;}
if(a<c&&b<d) return;
double x=(mx[id].b-ins.b)/(ins.k-mx[id].k);
if((double)(Mid)<x)
{
if(a>c)
{
change(rs,Mid+1,R,Mid+1,r,mx[id]);
mx[id]=ins;
}
else change(rs,Mid+1,R,Mid+1,r,ins);
}
else
{
if(a>c) change(ls,L,Mid,l,Mid,ins);
else
{
change(ls,L,Mid,l,Mid,mx[id]);
mx[id]=ins;
}
}
return;
}
if(r<=Mid) change(ls,L,Mid,l,r,ins);
else if(l>Mid) change(rs,Mid+1,R,l,r,ins);
else change(ls,L,Mid,l,Mid,ins),change(rs,Mid+1,R,Mid+1,r,ins);
}
void query(int id,int l,int r,int p,beecute &ret)
{
if(mx[id].id) ret=max(ret,beecute(mx[id].id,mx[id].pos(1.0*p)));
if(l==r) return;
int mid=l+r>>1;
if(p<=mid) query(ls,l,mid,p,ret);
else query(rs,mid+1,r,p,ret);
}
int main()
{
scanf("%d",&m);
for(int id=0,op,k,a,b,c,d,i=1;i<=m;i++)
{
scanf("%d",&op);
if(op)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
a=(a+las.id-1)%n+1,b=(b+las.id-1)%(int)(1e9)+1;
c=(c+las.id-1)%n+1,d=(d+las.id-1)%(int)(1e9)+1;
if(a>c) std::swap(a,c),std::swap(b,d);
if(a==c) bee[a]=max(bee[a],beecute(++id,1.0*max(b,d)));
else change(1,1,n,a,c,seg(a,b,c,d,++id));
}
else
{
scanf("%d",&k);
k=(k+las.id-1)%n+1;
las=bee[k];
query(1,1,n,k,las);
printf("%d\n",las.id);
}
}
return 0;
}

2019.2.14

洛谷 P4097 [HEOI2013]Segment 解题报告的更多相关文章

  1. 2018.07.23 洛谷P4097 [HEOI2013]Segment(李超线段树)

    传送门 给出一个二维平面,给出若干根线段,求出x" role="presentation" style="position: relative;"&g ...

  2. 洛谷P4097 [HEOI2013]Segment(李超线段树)

    题面 传送门 题解 调得咱自闭了-- 不难发现这就是个李超线段树,不过因为这里加入的是线段而不是直线,所以得把线段在线段树上对应区间内拆开之后再执行李超线段树的操作,那么复杂度就是\(O(n\log^ ...

  3. [洛谷P4097] [HEOI2013] Segment

    Description 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第 \(i\) 条被插入的线段的标号为 \(i\) 2.给定一个数 \(k\) ,询问与直线 \(x = k\ ...

  4. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...

  5. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  6. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  7. 洛谷 P3349 [ZJOI2016]小星星 解题报告

    P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...

  8. 洛谷 P3177 树上染色 解题报告

    P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...

  9. 洛谷 P4705 玩游戏 解题报告

    P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...

随机推荐

  1. DefWindowProc是一个会产生消息的函数

    先看一道题目: 当用户点击右上角关闭按钮的时候,请给下列Windows做出的响应排个序:A:发送 WM_QUIT 消息     B:发送 WM_CLOSE 消息     C:发送 WM_DESTROY ...

  2. python语言程序设计9

    1, 数字转换形式中有很多东西都不会,但是总不能放仍不管把? 总结点东西吧,比如 print()中增加end=""参数表示输入后不增加换行,多个print可以连续输出. 2, 我还 ...

  3. C#获取当前堆栈的各调用方法列表

    在使用.NET编写的代码在debug时很容易进行排查和定位问题,一旦项目上线并出现问题的话那么只能依靠系统日志来进行问题排查和定位,但当项目复杂时,即各种方法间相互调用将导致要获取具体的出错方法或调用 ...

  4. java使用何种类型表示精确的小数?

    问题 java使用何种类型表示精确的小数? 结论 float和double类型的主要设计目标是为了科学计算和工程计算,速度快,存在精度丢失 BigDecimal用来表示任意精确浮点数运算的类,在商业应 ...

  5. 《Linux内核设计》第17章学习笔记

  6. linux及安全第八周总结

    进程的调度时机与进程的切换 操作系统原理中介绍了大量进程调度算法,这些算法从实现的角度看仅仅是从运行队列中选择一个新进程,选择的过程中运用了不同的策略而已. 对于理解操作系统的工作机制,反而是进程的调 ...

  7. Beta版会议总结

    开会时间:2015年06月12日 开会地点:基教601 开会人员:李想,王颖瑞,朱少辉,陈晨,侯涛亮. 开会内容:对于6月10日,大一同学的投票情况进行讨论和反思. 讨论结果如下: 一.目前存在的问题 ...

  8. <<梦断代码>>阅读笔记三

    看完了这最后三分之一的<梦断代码>,意味着这本软件行业的著作已经被我粗略地过了一遍. 在这最后三分之一的内容中,我深入了解了在大型软件项目的运作过程中存在的困难和艰辛.一个大型软件项目的成 ...

  9. <<浪潮之巅>>阅读笔记二

    好的文章总是慢慢吸引着你去阅读,这本书的作者是吴军博士,让我很钦佩的是他还是一个很著名的程序员.其实我感觉理科生在写作方面的能力是很欠缺的,我们经常做到了有观点,但是做不到和别人表达清楚你的观点想法, ...

  10. SpringMVC-RESTRUL___CRUD知识点总结

    RESTful风格 <!-- 携带surveyId去后台 --><!-- RESTFUL风格:/xxx/23 --><!-- 接收方式:@PathVariable注解 - ...