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. linux atime ctime mtime

    touch testtime 1. stat testtime[为文件名] 可以查看这个文件名的三者状态 2.ll testtime;ll --time=atime testtime ;ll --ti ...

  2. Java基础知识强化之集合框架笔记68:Collections类概述和成员方法(备注:Collection 和 Collections区别)

    1. Collections类概述: 针对集合操作的工具类,都是静态方法.  2. Collection 和 Collections的区别: Collections是个java.util下的类,它包含 ...

  3. Nexus搭建Maven服务器

    参考:http://blog.csdn.net/ichsonx/article/details/14642897 1. 为什么使用Nexus 如果没有私服,我们所需的所有构件都需要通过maven的中央 ...

  4. javascript进击(六)Jquery

    引用 jQuery 如需测试 JavaScript 库,您需要在网页中引用它. 为了引用某个库,请使用 <script> 标签,其 src 属性设置为库的 URL: <!DOCTYP ...

  5. ERROR 1114 (HY000): The table 'adv_date_tmp' is full(Mysql临时表应用)

    场景:需要对现在数据库的数据进行批量的进行is_del=1的操作,但是遇到一个问题,在执行sql的时候发现sql不能在查询特定表的时候再嵌套查询来做update的操作,经过讨论,后续我们想到用临时表的 ...

  6. 史上最全的JavaScript工作笔记

    /* * JavaScript查看对象函数 */ function resultTest( obj ){ var resultTest = ''; $.each(obj,function(key,va ...

  7. PostgreSQL 修改列报错:cannot be cast automatically to type integer

    如果你直接使用可视化工具修改一个varchar字段为int类型的时候,可能会报错, 这里就需要自己去写一个语句去修改了 调整执行语句:ALTER TABLE table_name ALTER COLU ...

  8. Eclipes中使用BASE64Encoder及BASE64Decoder报错

    也没有提示让导包,这是因为Base64的加密解密都是使用sun.misc包下的BASE64Encoder及BASE64Decoder的sun.misc.BASE64Encoder/BASE64Deco ...

  9. SQL Server 阻止了对组件 'xp_cmdshell' 的 过程'sys.xp_cmdshell' 的访问

    sql server 2005: EXEC sp_configure N'show advanced options', N'1' RECONFIGURE WITH OVERRIDEEXEC sp_c ...

  10. 10_Mybatis开发Dao方法——mapper代理实现

    [工程截图(几个关键的标红框)] [UserMapper.xml] <?xml version="1.0" encoding="UTF-8"?> & ...