BZOJ3165: [Heoi2013]Segment(线段树)
来源:互联网 发布:convertfrom json 编辑:程序博客网 时间:2024/05/21 22:48
传送门
要求在平面直角坐标系下维护两个操作:
1.在平面上加入一条线段。记第i条被插入的线段的标号为i。
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号。
题解:
好题啊。。
可以假设目前每个区间只有一条线段覆盖(初始化为0),考虑新加入一条边的影响:
如果这条边在原边之上或者之下,那么直接保留较上面的边就行了。
如果有交点,那么一定有一条线段覆盖了区间的一半(交点的左边或者后边),那么这个区间保留这条线段,将另一条影响较小的线段下传到子树处理子问题就好了。每条线段减小一半,那么只会影响到
(注意处理线段退化为点的边界情况)
查询时查找根到节点的最大值即可。
Code:
#include<bits/stdc++.h>using namespace std;inline int read(){ char ch=getchar();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();} return i*f;} inline void W(int x){ static int buf[50]; if(!x){putchar('0');return;} while(x)buf[++buf[0]]=x%10,x/=10; while(buf[0])putchar(buf[buf[0]--]+'0');}const int Maxn=2e5+50,Rlim=39989;const int LIM=1e9;const double eps=1e-9;inline int sgn(double x){return (x>eps)-(x<-eps);}double ly[Maxn],ry[Maxn];int n,p,id,ind[Maxn],L,R,yc0,yc1,cnt;double mx;inline double calc(int l,double lc,int r,double rc,int pos){ if(l==r&&l==pos)return lc; double sp=(rc-lc)/(r-l); return (double)lc+sp*(pos-l);}inline double calc2(int l,int r,double lc1,double rc1,double lc2,double rc2){ double sp1=(rc1-lc1)/(r-l),sp2=(rc2-lc2)/(r-l); return (lc2-lc1)/(sp1-sp2)+l;}inline void upt(int k,int l,int r,double lc,double rc,int ii){ if(!ind[k]){ly[k]=lc,ry[k]=rc;ind[k]=ii;return;} if(l==r){ if(sgn(ly[k]-lc)<0)ly[k]=(ry[k]=lc),ind[k]=ii; return; } int t1=sgn(ly[k]-lc),t2=sgn(ry[k]-rc); if((t1>=0&&t2>=0&&ind[k]<ii)||(t1>0&&t2>0))return; if((t1<=0&&t2<=0&&ind[k]>ii)||(t1<0&&t2<0)){ly[k]=lc,ry[k]=rc;ind[k]=ii;return;} double pos=calc2(l,r,lc,rc,ly[k],ry[k]); int mid=(l+r)>>1; if(sgn(pos-mid)<=0){ if(sgn(ly[k]-lc)>=0&&sgn(ry[k]-rc)<=0){ double v=calc(l,ly[k],r,ry[k],mid),v2=ly[k]; ly[k]=lc,ry[k]=rc;upt(k<<1,l,mid,v2,v,ind[k]);ind[k]=ii; }else{ double v=calc(l,lc,r,rc,mid),v2=lc; upt(k<<1,l,mid,v2,v,ii); } }else{ if(sgn(ly[k]-lc<=0)&&sgn(ry[k]-rc)>=0){ double v=calc(l,ly[k],r,ry[k],mid+1),v2=ry[k]; ly[k]=lc,ry[k]=rc;upt(k<<1|1,mid+1,r,v,v2,ind[k]);ind[k]=ii; }else{ double v=calc(l,lc,r,rc,mid+1),v2=rc; upt(k<<1|1,mid+1,r,v,v2,ii); } }}inline void modify(int k,int l,int r,int ii){ if(L<=l&&r<=R){upt(k,l,r,calc(L,yc0,R,yc1,l),calc(L,yc0,R,yc1,r),ii);return;} int mid=(l+r)>>1; if(R<=mid)modify(k<<1,l,mid,ii); else if(L>mid)modify(k<<1|1,mid+1,r,ii); else modify(k<<1,l,mid,ii),modify(k<<1|1,mid+1,r,ii);}inline int query(int k,int l,int r,int pos){ if(l==r){ if(sgn(ly[k]-mx)>0||(sgn(ly[k]-mx)>=0&&ind[k]<id))mx=ly[k],id=ind[k]; return id; } double y=calc(l,ly[k],r,ry[k],pos); if(sgn(y-mx)>0||(sgn(y-mx)>=0&&ind[k]<id))mx=y,id=ind[k]; int mid=(l+r)>>1; return (pos<=mid)?(query(k<<1,l,mid,pos)):(query(k<<1|1,mid+1,r,pos));}int main(){ n=read(); for(int i=1;i<=n;i++){ int op=read(); if(op==1){ L=(read()+p-1)%Rlim+1,yc0=(read()+p-1)%LIM+1; R=(read()+p-1)%Rlim+1,yc1=(read()+p-1)%LIM+1; if(L>R)swap(L,R),swap(yc0,yc1); if(L==R)yc0=(yc1=max(yc0,yc1)); ++cnt;modify(1,1,Rlim,cnt); }else (mx=0,id=0,p=query(1,1,Rlim,(read()+p-1)%Rlim+1),W(p),putchar('\n')); }}
阅读全文
0 0
- BZOJ3165: [Heoi2013]Segment(线段树)
- 【bzoj3165】【HEOI2013】【Segment】【线段树】
- 【bzoj3165】[Heoi2013]Segment 神奇的线段树
- [李超线段树] BZOJ3165 [Heoi2013]. Segment
- 【李超线段树】BZOJ3165 [Heoi2013]Segment
- 【李超线段树】BZOJ3165(Heoi2013)[Segment]题解
- 【BZOJ3165】Segment(线段树)
- BZOJ3165: [Heoi2013]Segment
- BZOJ3165 Heoi2013 Segment
- bzoj3165 [Heoi2013]Segment
- 【bzoj3165】[Heoi2013]Segment
- [学习笔记][HEOI2013]BZOJ3165 Segment
- 【BZOJ】【P3165】【Heoi2013】【Segment】【题解】【线段树】
- BZOJ 3165 Heoi2013 Segment 线段树
- 李超线段树 [Heoi2013]Segment
- [线段树] BZOJ 3165: [Heoi2013]Segment
- [李超线段树] BZOJ 3165: [Heoi2013]Segment
- [ 李超线段树 ] BZOJ3165
- 字符编码
- 区间翻转问题 Splay
- PyQt5实时显示Camera
- python库之xlwt+xlrd+openpyxl
- 1041. 考试座位号(15) 结构体struct stu vector<stu> a(5);
- BZOJ3165: [Heoi2013]Segment(线段树)
- spring boot 404不匹配路径问题
- Java面试题大汇总
- 最小生成树Prim算法朴素版 C语言实现
- Java 基础总结
- ios自动更新(一)
- 给定Json数据格式,提取相关数据
- Unity3d 判断手势触摸的类型 ,判断手势的滑动方向,并获取刚触摸以及触摸结束事的坐标
- java面经----大公司必问