bzoj3165 [Heoi2013]Segment
2017-08-22 20:10
330 查看
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
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。
分析:
终于要学习新的数据结构了
灰常的兴奋啊~~
新知识的学习从抄板子开始
从零开始的数据结构学习。。。
丁队的板子。。。看不懂
只能上网找资源orz
李超线段树板子
要求在平面直角坐标系下维护两个操作:
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
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。
分析:
终于要学习新的数据结构了
灰常的兴奋啊~~
新知识的学习从抄板子开始
从零开始的数据结构学习。。。
丁队的板子。。。看不懂
只能上网找资源orz
李超线段树板子
这里写代码片 #include<cstdio> #include<cstring> #include<iostream> #include<cmath> using namespace std; const double eps=1e-10; const int swt=1000000000; const int N=100010; const int mod=39989; struct nd{ int x,y,ff; }; nd tree[N<<2]; struct node{ int x,y; double k,b; double f(int x){ return k*x+b; } }; node li ; //线段 int lastans,tot=0,ansi,wi ; double ansy,wy ; //ansy记录最大坐标,ansi记录线段编号 int dcmp(double x) { if (fabs(x)<eps) return 0; else if (x>0) return 1; else return -1; } int cross(int u,int w) //交点 { return floor((li[w].b-li[u].b)/(li[u].k-li[w].k)); } node getline(int x,int y,int xx,int yy) { node ans; ans.x=min(x,xx); //定义域 ans.y=max(x,xx); if (ans.x!=ans.y){ ans.k=(double)(yy-y)/(double)(xx-x); ans.b=y-x*ans.k; //kx+b=y } else ans.k=0.0,ans.b=max(y,yy); //一条竖线 return ans; } void update(int u,int x) //x=u和线段的交点 { double y=li[x].f(u); int p=dcmp(y-wy[u]); if (!wi[u]||(p>0||(p==0&&x<wi[u]))) { wy[u]=y; //维护端点值 wi[u]=x; } } void build(int bh,int l,int r) { tree[bh].x=l; tree[bh].y=r; tree[bh].ff=0; if (l==r) return; int mid=(l+r)>>1; build(bh<<1,l,mid); build(bh<<1|1,mid+1,r); } void insert(int bh,int u) //把每个线段分成logn个区间 { if (li[u].x<=tree[bh].x&&li[u].y>=tree[bh].y) //线段树节点完全包含线段 { if (!tree[bh].ff){ tree[bh].ff=u;return; ///没被覆盖过 } int mid=(tree[bh].x+tree[bh].y)>>1; int ll=dcmp(li[u].f(tree[bh].x)-li[tree[bh].ff].f(tree[bh].x)); int rr=dcmp(li[u].f(tree[bh].y)-li[tree[bh].ff].f(tree[bh].y)); //通过f函数计算线段树节点的左右端点与两条线段的交点 if (ll>0&&rr>0) //完全覆盖 tree[bh].ff=u; else if (ll>0||rr>0) //李超线段树的精髓啊 { int tt=cross(tree[bh].ff,u); if (tt<=mid&&ll>0) insert(bh<<1,u); if (tt<=mid&&rr>0) insert(bh<<1,u),tree[bh<<1|1].ff=u; // if (tt>mid&&rr>0) insert(bh<<1|1,u); if (tt>mid&&ll>0) insert(bh<<1|1,u),tree[bh<<1].ff=u; // } else update(tree[bh].x,u),update(tree[bh].y,u); return; } int mid=(tree[bh].x+tree[bh].y)>>1; if (li[u].x<=mid) insert(bh<<1,u); if (li[u].y>mid) insert(bh<<1|1,u); } void ask(int bh,int u) { if (tree[bh].ff) { double y=li[tree[bh].ff].f(u); int s=dcmp(y-ansy); if (s>0||(s==0&&ansi>tree[bh].ff)) ansy=y,ansi=tree[bh].ff; } if (tree[bh].x==tree[bh].y) return; int mid=(tree[bh].x+tree[bh].y)>>1; if (u<=mid) ask(bh<<1,u); if (u>mid) ask(bh<<1|1,u); } int main() { int T; scanf("%d",&T); build(1,1,mod); while (T--) { int opt,x,y,xx,yy; scanf("%d",&opt); if (opt==1) { scanf("%d%d%d%d",&x,&y,&xx,&yy); x=(x+lastans-1)%mod+1;y=(y+lastans-1)%swt+1; xx=(xx+lastans-1)%mod+1;yy=(yy+lastans-1)%swt+1; li[++tot]=getline(x,y,xx,yy); insert(1,tot); } else { scanf("%d",&x); x=(x+lastans-1)%mod+1; ansi=0;ansy=-1.0; ask(1,x); int s=dcmp(wy[x]-ansy); if (s>0||(s==0&&wi[x]<ansi)) ansi=wi[x]; lastans=ansi; printf("%d\n",lastans); } } }
相关文章推荐
- BZOJ3165 Heoi2013 Segment
- 【李超线段树】BZOJ3165(Heoi2013)[Segment]题解
- BZOJ3165 & 洛谷4097:[HEOI2013]Segment——题解
- [李超线段树] BZOJ3165 [Heoi2013]. Segment
- [线段树] BZOJ 3165: [Heoi2013]Segment
- BZOJ 3165: [Heoi2013]Segment 标记永久化
- 【李超线段树】BZOJ3165 [Heoi2013]Segment
- [李超线段树] BZOJ 3165: [Heoi2013]Segment
- BZOJ3165 : [Heoi2013]Segment
- [bzoj3165][Heoi2013]Segment——李超线段树
- 【HEOI2013】Segment
- bzoj 3165: [Heoi2013]Segment 线段树
- 李超线段树 [Heoi2013]Segment
- [Heoi2013]Segment
- BZOJ 3165 Heoi2013 Segment 线段树
- 【bzoj3165】【HEOI2013】【Segment】【线段树】
- 3165: [Heoi2013]Segment 线段树 标记永久化
- 【BZOJ 3165】 [Heoi2013]Segment 李超线段树
- [Heoi2013]Segment
- BZOJ 3165: [Heoi2013]Segment