Bzoj 3165 [Heoi2013]Segment题解
3165: [Heoi2013]Segment
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 668 Solved: 276
[Submit][Status][Discuss]
Description
要求在平面直角坐标系下维护两个操作:
1.在平面上加入一条线段。记第i条被插入的线段的标号为i。
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号。
Input
第一行一个整数n,表示共n 个操作。
接下来n行,每行第一个数为0或1。
若该数为 0,则后面跟着一个正整数 k,表示询问与直线
x = ((k +lastans–1)%39989+1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段y坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号。
若该数为 1,则后面跟着四个正整数 x0, y0, x 1, y 1,表示插入一条两个端点为
((x0+lastans-1)%39989+1,(y0+lastans-1)%10^9+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的线段。
其中lastans为上一次询问的答案。初始时lastans=0。
Output
对于每个 0操作,输出一行,包含一个正整数,表示交点最靠上的线段的编号。若不存在与直线相交的线段,答案为0。
Sample Input
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5
Sample Output
0 3
HINT
对于100%的数据,1 ≤ n ≤ 10^5 , 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。
这道题用到了李超线段树,由于不会,就上网强行看了一波题解+标程,然后一脸蒙蔽的打完了。
首先我们可以注意到x的数据范围比y要明显小得多,那么我们可以根据x建线段树,每一个节点代表一个x值,维护的内容就是当前区间内的最靠上的线段。
到这里可能有些人会和博主有一样的疑问,对于一个区间,他每个点的最优解可能来自多条直线,我们该怎么处理呢?这就是李超线段树强悍的地方了,对于这种情况我们不会因为到达当前要修改的位置而停止,而是接着向他的儿子们转移,这样,我们早晚可以让这条线段成为完全的最优解。
对于询问,李超线段树也和平常线段树不一样,首先对于无斜率的线段由于只可能有一个最优解,我们不必再把它放到线段树里面,而是单独记录,然后就从上往下进行查询,查到对应的单点为止,对于我们在路上碰到的节点的最优解我们都可以对我们的答案进行更新,因为他们都覆盖了目标节点。最后直接输出即可。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
#define N 40005
#define M 100005
using namespace std;
int n,p1=,p2=,la;
struct no
{
int left,right,mid;
int id;
}node[N*];
struct li
{
int x1,x2,y1,y2;
}line[M];
void build(int left,int right,int x)
{
node[x].left=left,node[x].right=right;
if(left==right)
return;
int mid=(left+right)/;
node[x].mid=mid;
build(left,mid,*x);
build(mid+,right,*x+);
}
double get_k(li a)
{
return double(a.y2-a.y1)/double(a.x2-a.x1);
}
int lmax[N][],zz;
void add(int left,int right,int x,int id)
{ if(!node[x].left)return;//为了防止到了单点还继续向下更新
if(node[x].left==left&&node[x].right==right)
{
if(!node[x].id)node[x].id=id;
else
{
double k1=get_k(line[node[x].id]);
double k2=get_k(line[id]);
double y1=double(line[node[x].id].y1)-k1*double(line[node[x].id].x1)+k1*left,y2=line[node[x].id].y1-k1*double(line[node[x].id].x1)+k1*right;
double y3=double(line[id].y1)-k2*double(line[id].x1)+k2*left,y4=line[id].y1-k2*double(line[id].x1)+k2*right;
if(y1>=y3&&y2>=y4)
return;
else if(y1<=y3&y2<=y4)
node[x].id=id;
else
{
int mid=node[x].mid;
add(left,mid,x*,id);
add(mid+,right,*x+,id);
}
}
return;
}
int mid=node[x].mid;
if(left>mid)
add(left,right,*x+,id);
else if(right<=mid)
add(left,right,*x,id);
else
add(left,mid,*x,id),add(mid+,right,*x+,id);
}
int ans;
double mx;
void get(int to,int x)
{
if(node[x].id)
{
double k=get_k(line[node[x].id]);
double y=double(line[node[x].id].y1)-k*double(line[node[x].id].x1)+k*to;
if(mx<y)
{
mx=y;
ans=node[x].id;
}
}
if(node[x].left==node[x].right)return;
int mid=node[x].mid;
if(to>mid)get(to,*x+);
else get(to,*x);
}
int main()
{
memset(lmax,-0x7f,sizeof(lmax));
scanf("%d",&n);
build(,p1,);
for(int i=;i<=n;i++)
{
int t;
scanf("%d",&t);
if(t==)
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1=(x1+la-)%p1+,y1=(y1+la-)%p2+;
x2=(x2+la-)%p1+,y2=(y2+la-)%p2+;
zz++;
line[zz].x1=x1,line[zz].x2=x2,line[zz].y1=y1,line[zz].y2=y2;
if(x1==x2)
{
if(y1>y2) swap(y1,y2);
if(lmax[x1][]<y2) lmax[x1][]=zz,lmax[x1][]=y2;
}
else
{
if(x1>x2)swap(x1,x2);//不要忘记左右端点大小顺序
add(x1,x2,,zz);
}
}
else
{
int x;
scanf("%d",&x);
x=(x+la-)%p1+;
mx=lmax[x][];
ans=lmax[x][];
if(ans==lmax[][])ans=;
get(x,);
printf("%d\n",ans);
la=ans;
}
}
return ;
}
Bzoj 3165 [Heoi2013]Segment题解的更多相关文章
- bzoj 3165: [Heoi2013]Segment 动态凸壳
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 202 Solved: 89[Submit][Stat ...
- BZOJ 3165: [Heoi2013]Segment
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 465 Solved: 187[Submit][Sta ...
- BZOJ.3165.[HEOI2013]Segment(李超线段树)
BZOJ 洛谷 对于线段,依旧是存斜率即可. 表示精度误差一点都不需要管啊/托腮 就我一个人看成了mod(10^9+1)吗.. //4248kb 892ms #include <cstdio&g ...
- bzoj 3165: [Heoi2013]Segment 线段树
题目: Description 要求在平面直角坐标系下维护两个操作: 在平面上加入一条线段.记第i条被插入的线段的标号为i. 给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. ...
- BZOJ3165 & 洛谷4097:[HEOI2013]Segment——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3165 https://www.luogu.org/problemnew/show/P4097 要求 ...
- Bzoj 3166 [Heoi2013] Alo 题解
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1118 Solved: 518[Submit][Status ...
- 【BZOJ3165】[HEOI2013]Segment(李超线段树)
[BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cst ...
- BZOJ 1003 物流运输 题解 【SPFA+DP】
BZOJ 1003 物流运输 题解 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的 ...
- BZOJ 1191 超级英雄 Hero 题解
BZOJ 1191 超级英雄 Hero 题解 Description 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金 ...
随机推荐
- Visual Studio 2015 和 Apache Cordova 跨平台开发入门
原文:Visual Studio 2015 和 Apache Cordova 跨平台开发入门(一) 基于 Windows 10 的 Visual Studio 2015 跨平台的应用开发主要分为基于V ...
- Win8Metro(C#)数字图像处理--2.15图像霓虹效果
原文:Win8Metro(C#)数字图像处理--2.15图像霓虹效果 [函数名称] 图像霓虹效果函数NeonProcess(WriteableBitmap src) 上述公式进行开方即可. [函 ...
- 微信小程序把玩(二十四)toast组件
原文:微信小程序把玩(二十四)toast组件 toast消息提示框,可用在提示一些信息,比如清楚缓存给用户一个友好的提示!或操作一些请求不想让用户有什么操作,toast也可以做到因为toast显示时其 ...
- oracle 使用db_link 导入导出小结
客户有一个需求,是将一个库中的某个用户迁移到一台新的oracle服务器上,因数据量较小,并且不涉及版本的升级,所以可以采用创建一个dblink,然后通过这个dblink直接从源库将用户数据导出并导入到 ...
- UWP入门(八)--几个简单的控件
原文:UWP入门(八)--几个简单的控件 每天看几个,要不聊几天我就可以看完啦,加油! 看效果 1. CheckBox <TextBlock Grid.Row="0" Tex ...
- 【UWP开发】uwp应用安装失败
原文:[UWP开发]uwp应用安装失败 编译出了uwp应用.appx之后双击打开,报错你需要为此应用包而安装的新证书,或者是带有受信任证书的新应用包.系统管理员或应用开发人员可以提供帮助.证书链在不受 ...
- 让bootstrap表格自动出现水平滚动条
<div class="table-responsive"><!--表格自动出现水平滚动条-> <table id="tb_departme ...
- Dynamic linking is coming to iOS, tvOS, and watchOS ports of Qt in the 5.9 release
http://blog.qt.io/blog/2017/01/23/qt-5-8-released/ Dynamic linking is coming to iOS, tvOS, and watch ...
- 【canvas】基础练习一 图形
Demo1[绘制一条线] <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- 95+强悍的jQuery图形效果插件
现在的网站越来越离不开图形,好的图像效果能让你的网站增色不少.通过JQuery图形效果插件可以很容易的给你的网站添加一些很酷的效果. 使用JQuery插件其实比想象的要容易很多,效果也超乎想象.在本文 ...