洛谷 P4097 [HEOI2013]Segment 解题报告
P4097 [HEOI2013]Segment
题目描述
要求在平面直角坐标系下维护两个操作:
- 在平面上加入一条线段。记第 \(i\) 条被插入的线段的标号为 \(i\)
- 给定一个数 \(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 解题报告的更多相关文章
- 2018.07.23 洛谷P4097 [HEOI2013]Segment(李超线段树)
传送门 给出一个二维平面,给出若干根线段,求出x" role="presentation" style="position: relative;"&g ...
- 洛谷P4097 [HEOI2013]Segment(李超线段树)
题面 传送门 题解 调得咱自闭了-- 不难发现这就是个李超线段树,不过因为这里加入的是线段而不是直线,所以得把线段在线段树上对应区间内拆开之后再执行李超线段树的操作,那么复杂度就是\(O(n\log^ ...
- [洛谷P4097] [HEOI2013] Segment
Description 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第 \(i\) 条被插入的线段的标号为 \(i\) 2.给定一个数 \(k\) ,询问与直线 \(x = k\ ...
- 洛谷 P1783 海滩防御 解题报告
P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...
- 洛谷 P4597 序列sequence 解题报告
P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...
- 洛谷1087 FBI树 解题报告
洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...
- 洛谷 P3349 [ZJOI2016]小星星 解题报告
P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...
- 洛谷 P3177 树上染色 解题报告
P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...
- 洛谷 P4705 玩游戏 解题报告
P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...
随机推荐
- CF [2016-2017 ACM-ICPC CHINA-Final][GYM 101194 H] Great Cells
很久以前做的一道思博题了,今天来补一补. 大致题意:在一个\(n*m\)的矩阵内填整数,数字在\([1,k]\)范围内.矩阵中某格的数为great number当且仅当与它同行同列的数字都严格比它小. ...
- SAAS云平台搭建札记: (一) 浅论SAAS多租户自助云服务平台的产品、服务和订单
最近在做一个多租户的云SAAS软件自助服务平台,途中遇到很多问题,我会将一些心得.体会逐渐分享出来,和大家一起探讨.这是本系列的第一篇文章. 大家知道,要做一个全自助服务的SAAS云平台是比较复杂的, ...
- AT2134 Zigzag MST
题面 题解 这个题目主要是连边很奇怪,但是我们可以发现一个性质:权值是递增的. 于是像下图的连边:(加边方式为\((A_1, B_1, 1)\)) 其实可以等价于如下连边: 于是我们将其变成了在环上连 ...
- c++多继承布局
1:多重继承 对于一个继承了多个base class 的对象,将其地址指定给最左端(也就是第一个)base class的指针, 情况将和单一继承时相同,因为两者都指向相同的其实地址.至于第二个或者更后 ...
- 关于Prometheus运维实践项目
关于Promethues运维实践项目 1. 什么是Prometheus运维实践项目 是什么 Prometheus,普罗米修斯,是古希腊神话中为人间带来火种的神. Prometheus运维实 ...
- C#_Math函数总结
Math.abs() 计算绝对值. Math.acos() 计算反余弦值. Math.asin() 计算反正弦值. Math.atan() 计算反正切值. Math.atan2() 计算从x 坐标轴到 ...
- Mongo 开发笔记
时间 程序的时间是本地时间 ,数据库中的时间是 ISO 标准时间 . ISO时间 + 8 小时 = 本地时间(北京时间 ) Java驱动会自动做转化. 语法 数组查询 数据查询使用 elemMatch ...
- Python-复习-习题-13
复习 dict: dic = {'name':'alex'}增:dic['age'] = 21 存在就覆盖dic.setdefault() 存在什么也不做,没有就增加 删除:pop()按照key删除, ...
- Linux内核分析——第七章 链接
第七章——链接 1.链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载到存储器并执行. 2.链接可以执行于编译时,加载时,运行时. 7.1编译器驱动程序 1.大多数编译系 ...
- [what is machine learning?]
1.2 [what is machine learning?] 1.人:observation --> learing --> skill 机器:data --> ML --& ...