博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Heoi2013]Segment
阅读量:6499 次
发布时间:2019-06-24

本文共 3742 字,大约阅读时间需要 12 分钟。

Description

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

Input

第一行一个整数n,表示共n个操作。
接下来n行,每行第一个数为01
若该数为0,则后面跟着一个正整数k,表示询问与直线 x=((k+lastans1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段y坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号。
若该数为1,则后面跟着四个正整数x0,y0,x1,y1,表示插入一条两个端点为 ((x0+lastans1)%39989+1,(y0+lastans1)%109+1)((x1+lastans1)%39989+1,(y1+lastans1)%109+1) 的线段。其中lastans为上一次询问的答案。初始时lastans=0

Output

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

Sample Input

6
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5

Sample Output

2
0
3

HINT

对于100%的数据,1n105 , 1k,x0,x1399891y0y1109

Source

思路

这道题显然可以用线段树维护。
怎么维护?神奇的线段树标记永久化。
线段树上的节点存这个点的“优势线段”,即完全覆盖这个区间的线段中是最多点的最优解的线段,最终统计答案就从根节点向下搜索到叶子节点,经过树上区间的最优解就是这个点的最优解。
举个例子:
引用大佬图解
(图片出自,虽然我不知道这个网站是谁创的)
在这个图中,红色代表线段树上的寻找的区间,蓝色代表插入,黑色代表原来这个区间的最优线段,橙色代表这个区间的mid
可以看出,这个区间显然是蓝色线段占优势,而黑色线段在这个线段的右半部分占优势,并且黑色线段在左半部分完全没有存在的必要了。
那么这个点的值就是蓝色线段的编号,而这个点右儿子的值就是黑色线段的编号。
具体过程……看代码吧。

代码

#include 
#include
const int maxn=100000;const int maxx=39989;const int maxy=1000000000;int lastans,n;struct segment_tree//线段树{ struct line//记录一条线段 { int l,r;//这个是左端点和右端点的横坐标 double k,b;//这个是线段所处的直线y=kx+b中的k和b值 double f(int x)//这个是当横坐标为x时纵坐标的值 { return k*x+b; } }; line li[maxn+10]; int val[(maxn<<2)+10],totl,qans;//totl是线段总数,qans是询问的答案 double topv;//topv是询问的最优点的纵坐标 int query(int now,int left,int right,int pos) //查询left到right区间内是否右pos的最优值 { if((pos
right))//如果要找到不在这个区间就退出 { return 0; } if(val[now])//如果这个区间有完全被线段覆盖 { double ff=li[val[now]].f(pos); //ff是这个区间优势线段在pos这个横坐标的纵坐标值 if((topv
>1;//递归寻找左右儿子 query(now<<1,left,mid,pos); query(now<<1|1,mid+1,right,pos); return 0; } int insert(int now,int left,int right,int insv) //这个是插入一条编号为insv的线段 { if((li[insv].l>right)||(li[insv].r
0; int uor=(li[insv].f(right)-li[val[now]].f(right))>0; //uol是在区间左端点时插入的线段的纵坐标是否大于原线段的 //uor是在区间右端点时插入的线段的横坐标是否大于原线段的 if((!val[now])||(uol&&uor)) //如果这个区间还没有值,或者插入线段完全高于原线段,就直接赋值 { val[now]=insv; } else if(uol^uor) //如果两线段在这个区间有交点,就需要分情况讨论 { int mid=(left+right)>>1; double c=(li[insv].b-li[val[now]].b)/(li[val[now]].k-li[insv].k); if((c<=mid)&&uol) //原线段完全覆盖右区间,在左区间与插入线段分割 { insert(now<<1,left,mid,insv); //显然只在左侧插入要插入的线段就好了 } else if((c<=mid)&&uor) //插入线段完全覆盖右区间,在左区间与原线段分割 { insert(now<<1,left,mid,val[now]); val[now]=insv; } else if((c>mid)&&uol) //插入线段完全覆盖左区间,在右区间与原线段分割 { insert(now<<1|1,mid+1,right,val[now]); val[now]=insv; } else if((c>mid)&&uor) //原线段完全覆盖左区间,在有区间与插入线段分割 { insert(now<<1|1,mid+1,right,insv); } } } else//如果这个区间一半被覆盖,一半没有 { //这个区间不讨论,分到下面区间讨论 int mid=(left+right)>>1; insert(now<<1,left,mid,insv); insert(now<<1|1,mid+1,right,insv); } return 0; } int ins(int xa,int ya,int xb,int yb) //插入一条起点坐标为(xa,ya),终点坐标为(xb,yb)的线段 { ++totl;//记录这一条线段,赋编号 li[totl].l=std::min(xa,xb);//左侧的横坐标 li[totl].r=std::max(xa,xb);//右侧的横坐标 if(xa!=xb)//如果有斜率 { li[totl].k=(double)(yb-ya)/(xb-xa);//计算斜率 li[totl].b=ya-li[totl].k*xa;//计算截距 } else { li[totl].k=0; li[totl].b=std::max(ya,yb); //没有斜率这样处理,因为寻找时f(x)=b=max(ya,yb) } insert(1,1,maxx,totl);//在线段树中插入 return 0; } int ask(int x) { qans=0;//给qans和topv赋初值 topv=-maxy; query(1,1,maxx,x);//在线段树中查找 return qans; }};segment_tree st;int main(){ scanf("%d",&n); while(n--) { int kind,a,b,c,d; scanf("%d",&kind);//kind代表询问的种类 if(kind) { scanf("%d%d%d%d",&a,&b,&c,&d); st.ins((a+lastans-1)%maxx+1,(b+lastans-1)%maxy+1,(c+lastans-1)%maxx+1,(d+lastans-1)%maxy+1); //计算出要求插入的值 } else { scanf("%d",&a); lastans=st.ask((a+lastans-1)%maxx+1); //计算出要求询问的值,并更新lastans printf("%d\n",lastans); } } return 0;}

转载于:https://www.cnblogs.com/Canopus-wym/p/10376276.html

你可能感兴趣的文章
concurrent包的实现示意图
查看>>
golang os.Args
查看>>
Linux常用命令
查看>>
spring-data-elasticsearch 概述及入门(二)
查看>>
Solr启动和结束命令
查看>>
1.12 xshell密钥认证
查看>>
3.2 用户组管理
查看>>
VMware虚拟机出现“需要整合虚拟机磁盘”的解决方法
查看>>
ibatis 动态查询
查看>>
汇编语言之实验一
查看>>
git 调用 Beyond Compare
查看>>
SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)[转]
查看>>
android实现图片识别的几种方法
查看>>
mvc学习地址
查看>>
masonry 基本用法
查看>>
使用openssl创建自签名证书及部署到IIS教程
查看>>
Word产品需求文档,已经过时了【转】
查看>>
dtoj#4299. 图(graph)
查看>>
关于网站的一些js和css常见问题的记录
查看>>
zabbix-3.4 触发器
查看>>