3165: [Heoi2013]Segment

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 202  Solved: 89
[Submit][Status]

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)%109+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%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%的数据,1 ≤ n ≤ 10^5 , 1 ≤  k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。

  据说这道题可以用线段树裸搞,但是我用的是线段树维护下凸壳,考试时候如果询问坐标x值有垂直线段的话,我直接输出的垂直线段,没有考虑线段高度问题,导致wa了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<cmath>
using namespace std;
#define PROB "segment"
#define MAXN 60000
#define MAXT MAXN*17
#define VAL1 39989
#define VAL2 1000000000
#define lch (now<<1)
#define rch (now<<1^1)
#define INF 0x3f3f3f3f
inline int nextInt()
{
register int x=;
register char ch;
while (ch=getchar(),ch<'' || ch>'');
while (x=x*+ch-'',ch=getchar(),ch<='' && ch>='');
return x;
}
typedef double real;
const int maxval=;
struct point
{
real x,y;
point(){}
point(real x,real y):x(x),y(y){}
point(int x,int y):x(x),y(y){}
void print()
{
printf("(%.2lf,%.2lf) ",x,y);
}
};
struct line
{
point ps;
real x,y;
real angle;
line(){}
line(point p1,point p2)
{
ps=p1;
x=p2.x-p1.x;
y=p2.y-p1.y;
angle=atan(y/x);
}
real cross_height(real xx)
{
// if (xx<ps.x || xx>ps.x+x)return -1e10;
return ps.y + y*(xx-ps.x)/x;
}
point spos()
{
return ps;
}
point tpos()
{
return point(ps.x+x,ps.y+y);
}
void print()
{
printf("Line:");
spos().print();
tpos().print();
printf("\n");
}
}ll[MAXN];
inline real xmul(line &l1,line l2)
{
return (l1.x*l2.y)-(l1.y*l2.x);
}
inline bool parallel(line &l1,line &l2)
{
return xmul(l1,l2)==;
}
inline point crossover(line &l1,line &l2)
{
real s1=xmul(l1,line(l1.ps,l2.ps));
real s2=-xmul(l1,line(l1.ps,l2.tpos()));
return point(l2.ps.x+l2.x*s1/(s1+s2),
l2.ps.y+l2.y*s1/(s1+s2));
}
int L[MAXT],R[MAXT],S[MAXT];
int V[MAXT];
real spos[MAXT],tpos[MAXT];
int topt;
#define update(now) S[now]=S[L[now]]+S[R[now]]+1;
#define l_rotate(now)\
t=R[now];\
R[now]=L[t];update(now);\
L[t]=now;update(t);\
now=t;
#define r_rotate(now)\
t=L[now];\
L[now]=R[t];update(now);\
R[t]=now;update(t);\
now=t;
inline void maintain(int &now)
{
register int t;
if (S[L[L[now]]]>S[R[now]])
{
r_rotate(now);
maintain(L[now]);
maintain(R[now]);
maintain(now);
return ;
}else if (S[R[R[now]]]>S[L[now]])
{
l_rotate(now);
maintain(R[now]);
maintain(L[now]);
maintain(now);
return ;
}else if (S[R[L[now]]]>S[R[now]])
{
l_rotate(L[now]);
r_rotate(now);
maintain(R[now]);
maintain(L[now]);
maintain(now);
return ;
}else if (S[L[R[now]]]>S[L[now]])
{
r_rotate(R[now]);
l_rotate(now);
maintain(R[now]);
maintain(L[now]);
maintain(now);
return ;
}
}
int Insert(int &now,int id)
{
if (!now)
{
now=++topt;
V[now]=id;
S[now]=;
return now;
}
int ret;
if (ll[id].angle<ll[V[now]].angle)
ret=Insert(L[now],id);
else
ret=Insert(R[now],id);
update(now);
maintain(now);
return ret;
}
void Delete(int &now,int aim)
{
if (now==aim)
{
if (!L[now] && !R[now])
{
now=;
return ;
}
if (!L[now])
now=R[now];
else if (!R[now])
now=L[now];
else
{
register int t;
r_rotate(now);
Delete(R[now],aim);
}
update(now);maintain(now);
return ;
}
if (ll[V[aim]].angle < ll[V[now]].angle ||
(ll[V[aim]].angle==ll[V[now]].angle && aim<now))
Delete(L[now],aim);
else
Delete(R[now],aim);
update(now);
maintain(now);
}
int Get_rank(int &now,int aim)
{
if (now==aim)return S[L[now]]+;
if (ll[V[aim]].angle < ll[V[now]].angle ||
(ll[V[aim]].angle==ll[V[now]].angle && aim<now))
return Get_rank(L[now],aim);
else
return S[L[now]]++Get_rank(R[now],aim);
}
int Get_kth(int &now,int rk)
{
if (rk==S[L[now]]+)return now;
if (rk<S[L[now]]+)
return Get_kth(L[now],rk);
else
return Get_kth(R[now],rk-S[L[now]]-);
}
int spos_lower_bound(int &now,int ps)
{
if (!now)return -INF;
if (spos[now]<ps)
{
int ret=spos_lower_bound(R[now],ps);
if (ret!=-INF)return ret;
else return now;
}else
{
return spos_lower_bound(L[now],ps);
}
}
void Scan(int now)
{
if (!now)return;
Scan(L[now]);
ll[V[now]].print();
printf(" At[%.2lf,%.2lf]\n",spos[now],tpos[now]);
Scan(R[now]);
} void Insert_line(int &root,int lid)
{
register int cur=Insert(root,lid);
register int pa,pn;
pa=pn=-;
register int rk;
point pt;
rk=Get_rank(root,cur);
while (true)
{
if (rk==)break;
pa=Get_kth(root,rk-);
if (parallel(ll[V[pa]],ll[lid]))
{
if (ll[V[pa]].cross_height()>=ll[lid].cross_height())
{
Delete(root,cur);
return ;
}else
{
Delete(root,pa);
rk--;
continue;
}
}
pt=crossover(ll[V[pa]],ll[lid]);
tpos[pa]=pt.x;
if (tpos[pa]<=spos[pa])
{
Delete(root,pa);
rk--;
}
else
break;
}
if (rk==)
spos[cur]=-1e10;
else
spos[cur]=pt.x;
//rk=Get_rank(root,cur);
while (true)
{
if (rk==S[root])break;
pn=Get_kth(root,rk+);
if (parallel(ll[V[pn]],ll[lid]))
{
if (ll[V[pn]].cross_height()>=ll[lid].cross_height())
{
Delete(root,cur);
return ;
}else
{
Delete(root,pn);
continue;
}
}
pt=crossover(ll[V[pn]],ll[lid]);
spos[pn]=pt.x;
if (tpos[pn]<=spos[pn])
Delete(root,pn);
else
break;
}
if (rk==S[root])
tpos[cur]=1e10;
else
tpos[cur]=pt.x;
if (spos[cur]>=tpos[cur])
{
Delete(root,cur);
if (~pa && ~pn)
spos[pn]=tpos[pa]=crossover(ll[V[pa]],ll[V[pn]]).x;
else if (pa==-)
tpos[pn]=1e10;
else
spos[pa]=-1e10;
}
}
pair<real,int> Search(int &root,int pos)
{
pair<real,int> res;
int cur=spos_lower_bound(root,pos);
if (cur==-INF)return make_pair(-1e100,);
res.second=V[cur];
res.first=ll[V[cur]].cross_height(pos);
int rk=Get_rank(root,cur);
if (rk==S[root])return res;
int pa=Get_kth(root,rk+);
if (spos[pa]==pos)
{
res=min(res,make_pair(res.first,V[pa]));
}
return res;
}
struct sgt_node
{
int l,r;
int root;
}sgt[MAXT*];
void Build_sgt(int now,int l,int r)
{
sgt[now].l=l;sgt[now].r=r;
if (l+==r)return ;
int mid=(l+r)>>;
Build_sgt(lch,l,mid);
Build_sgt(rch,mid,r);
}
void Add_sgt(int now,int l,int r,int x,int y,int lid)
{
if (l==x && r==y)
{
Insert_line(sgt[now].root,lid);
return ;
}
int mid=(l+r)>>;
if (y<=mid)
Add_sgt(lch,l,mid,x,y,lid);
else if (mid<=x)
Add_sgt(rch,mid,r,x,y,lid);
else
{
Add_sgt(lch,l,mid,x,mid,lid);
Add_sgt(rch,mid,r,mid,y,lid);
}
}
pair<real,int> Query_sgt(int now,int l,int r,int pos)
{
pair<real,int> res=Search(sgt[now].root,pos);
res.second=-res.second;
if (l+==r)return res;
int mid=(l+r)>>;
if (pos<mid)
return max(res,Query_sgt(lch,l,mid,pos));
else if (mid<pos)
return max(res,Query_sgt(rch,mid,r,pos));
else
return max(res,max(Query_sgt(lch,l,mid,pos),Query_sgt(rch,mid,r,pos))); } pair<int,int> ignall[MAXN];
int main()
{
freopen(PROB".in","r",stdin);
//freopen(PROB".out","w",stdout);
int n,m,x,y,z;
int a,b,c,d;
int opt;
int lastans=;
m=nextInt();
// scanf("%d",&m);
Build_sgt(,,maxval);
n=;
for (int i=;i<=m;i++)
{
opt=nextInt();
//scanf("%d",&opt);
if (opt==)
{
x=nextInt();
//scanf("%d\n",&x);
x=((x+lastans-)%VAL1+);
if (ignall[x]!=make_pair(,))
{
//printf("%d\n",lastans=ignall[x].second);
pair<real,int> res=Query_sgt(,,maxval,x);
res.second=-res.second;
if(ignall[x].first>res.first)
printf("%d\n",lastans=ignall[x].second);
else
printf("%d\n",lastans=res.second);
continue;
}
pair<real,int> res=Query_sgt(,,maxval,x);
res.second=-res.second;
printf("%d\n",lastans=res.second);
}else
{
a=nextInt(),b=nextInt(),c=nextInt(),d=nextInt();
//scanf("%d%d%d%d",&a,&b,&c,&d);
a=(a+lastans-)%VAL1+;
c=(c+lastans-)%VAL1+;
b=(b+lastans-)%VAL2+;
d=(d+lastans-)%VAL2+;
if (a>c)swap(a,c),swap(b,d);
if (a==c)
{
if (ignall[a].first<max(b,d))
ignall[a]=make_pair(max(b,d),n);
n++;
continue;
}
ll[n++]=line(point(a,b),point(c,d));
Add_sgt(,,maxval,a,c,n-);
}
}
}

bzoj 3165: [Heoi2013]Segment 动态凸壳的更多相关文章

  1. BZOJ 3165: [Heoi2013]Segment

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

  2. Bzoj 3165 [Heoi2013]Segment题解

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

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

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

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

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

  5. BZOJ 3672 [Noi2014]购票 (熟练剖分+凸壳维护)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3672 题意:给出一棵有根树(1为根),边有长度.每个点u有三个属性(len[u], ...

  6. BZOJ.1007.[HNOI2008]水平可见直线(凸壳 单调栈)

    题目链接 可以看出我们是要维护一个下凸壳. 先对斜率从小到大排序.斜率最大.最小的直线是一定会保留的,因为这是凸壳最边上的两段. 维护一个单调栈,栈中为当前可见直线(按照斜率排序). 当加入一条直线l ...

  7. bzoj 1007 凸壳

    首先明确一个概念 左面内个叫上凸壳,右面那个叫下凸壳 然后我们只需要维护一个上图壳就行了,先按着斜率排序,每次加进来一条边,判断tot边和这个边与tot-1边的交点横坐标, 如果这条边的横坐标小就一直 ...

  8. 【BZOJ3165】[HEOI2013]Segment(李超线段树)

    [BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cst ...

  9. [BZOJ2726][SDOI2012]任务安排(DP+凸壳二分)

    2726: [SDOI2012]任务安排 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1580  Solved: 466[Submit][Statu ...

随机推荐

  1. SAXParser 解析器和 XMLEventReader(读取XML文档)

    import javax.xml.parsers.ParserConfigurationException;import javax.xml.parsers.SAXParser;import java ...

  2. jquery动态添加列表后样式失效解决方式

    最近在做一个通讯录,使用jquery mobile方式来做,在动态添加列表后,listview原有的样式失效,折腾一会,找出解决办法.代码如下. <%@ page language=" ...

  3. 重载public Primes ():this(2,100)

    当构造函数有多个重载的时候 想通过默认构造函数调用其他的重载的构造函数的话 就可以用:运算符public Primes():this(2, 100){//code }public Primes(int ...

  4. 构建本地yum源之rpmbuild问题汇总

    - check-rpaths的问题 今天在编译varnish的时候,遇到几个问题,其中一个就是出现如下错误: ...+ /usr/lib/rpm/check-rpaths /usr/lib/rpm/c ...

  5. modelsim将波形文件保存下来却不打开图形界面

    vsim -c -do sim.tcl -l sim.log 波形怎么保存啊,我想把波形保存下来,但不显示,想看那个信号时在加上,不然信号全部出来了太乱了 在do文件里写add wave -r *ru ...

  6. JQuery_AJAX简单笔记

    <script type="text/javascript"> //Ajax方法 $.ajax({ type: "post", cache: fal ...

  7. mysql中 的 ENGINE = innodb; 是什么意思?

    存储引擎是innodb.nnoDB 是 MySQL 上第一个提供外键约束的数据存储引擎,除了提供事务处理外,InnoDB 还支持行锁,提供和 Oracle 一样的一致性的不加锁读取,能增加并发读的用户 ...

  8. HOOK函数(二)——全局HOOK

    如果钩子函数定义于当前进程相关的线程中,则钩子函数只能处理当前进程的线程的消息,如果要想处理当前正在运行的所有进程的鼠标消息和键盘消息,那么安装钩子函数的代码必须实现在动态链接库中.所以如果想让安装的 ...

  9. Angularjs总结(八)$ cookie和$rootscope

    AngularJS 提供了很好的 $cookie 和 $cookieStore API 用来处理 cookies .这两个服务都能够很好的发挥HTML5 cookies,当HTML5 API可用时浏览 ...

  10. (一)JAVA使用POI操作excel

    1,Poi 简介 Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能 PO ...