bzoj 3165: [Heoi2013]Segment 动态凸壳
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
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值有垂直线段的话,我直接输出的垂直线段,没有考虑线段高度问题,导致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 动态凸壳的更多相关文章
- BZOJ 3165: [Heoi2013]Segment
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 465 Solved: 187[Submit][Sta ...
- Bzoj 3165 [Heoi2013]Segment题解
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 668 Solved: 276[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相交的线段中,交点最靠上的线段的编号. ...
- BZOJ 3672 [Noi2014]购票 (熟练剖分+凸壳维护)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3672 题意:给出一棵有根树(1为根),边有长度.每个点u有三个属性(len[u], ...
- BZOJ.1007.[HNOI2008]水平可见直线(凸壳 单调栈)
题目链接 可以看出我们是要维护一个下凸壳. 先对斜率从小到大排序.斜率最大.最小的直线是一定会保留的,因为这是凸壳最边上的两段. 维护一个单调栈,栈中为当前可见直线(按照斜率排序). 当加入一条直线l ...
- bzoj 1007 凸壳
首先明确一个概念 左面内个叫上凸壳,右面那个叫下凸壳 然后我们只需要维护一个上图壳就行了,先按着斜率排序,每次加进来一条边,判断tot边和这个边与tot-1边的交点横坐标, 如果这条边的横坐标小就一直 ...
- 【BZOJ3165】[HEOI2013]Segment(李超线段树)
[BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cst ...
- [BZOJ2726][SDOI2012]任务安排(DP+凸壳二分)
2726: [SDOI2012]任务安排 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1580 Solved: 466[Submit][Statu ...
随机推荐
- opai_suki
- 实现方法 C# button快捷键
本文讲解了三种方法实现C# button快捷键,如Alt + *(按钮快捷键),Ctrl+*及其他组合键等. C# button快捷键之第一种:Alt + *(按钮快捷键) 在大家给button.la ...
- mysql常见问题
Q:ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.1.111' (61)A: 找到my.cnf,把#bind-addres ...
- Candence下对“跨页连接器(off-page connector)”进行批量重命名的方法
parts.ports.alias等等均可以在“属性编辑器(Property Editor)”中进行查看编辑,并通过复制到Excel等表格软件来进行批量修改.之后再粘贴回去的方法进行批量编辑.但是“跨 ...
- 用变量a给出下面的定义
a)一个整型数(An integer)b) 一个指向整型数的指针(A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to ...
- iOS NSNumber语法糖
BOOL equal; NSNumber * num1 = [NSNumber numberWithInteger:]; NSNumber * num2 = @; equal = [num1 isEq ...
- Struts2的输入校验
一.Struts2提供了基于验证框架的输入校验,在这种校验方式下,所有的输入校验只需要编写简单的配置文件,Struts2的验证框架将会负责进行服务器校验和客户端校验. 校验失败后将Struts2将自动 ...
- ZOJ 1025 Wooden Sticks(快排+贪心)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=25 题目大意:机器运送n个木条,每个木条有一个长度和重量.运送第一根木 ...
- [zz]安装Ubuntu 15.10后要做的事
很有用,收藏 http://blog.csdn.net/skykingf/article/details/45267517
- HBuilder手机Iphone运行提示“未受信用的企业级开发者”
HBuilder手机Iphone运行提示“未受信用的企业级开发者” 解决方法:设置-----通用------设备管理-----点击Digtial Heaven....---信任"Digtia ...