【UOJ】#242. 【UR #16】破坏蛋糕
2017-01-19 22:57
351 查看
传送门http://uoj.ac/problem/242
貌似出题人给的方法一点都不友好QwQ
那个如果一个平面是有限的,那么它被分为两部分,这两部分都是有限的。
假设我们要求的那条直线是y轴(不是也可以转),那么考虑对直线左右分别计算平面是否有限。
就直线右侧而言,我们把交点按照顺序排好。交点ya和yb之间的区间对应平面是有限的,当且仅当存在yc和yd,满足yd≤yb≤ya≤yc,且kc<kd。
其中c,d可以是a,b,k代表交点对应直线斜率。
感性认识一下吧……
那么先说一下把要求的直线旋到y轴的原因:好判断啊,一边的直线斜率全是连续的了。但是旋转后平行难判,要用原始坐标判断。
那么考虑一下如何维护相交。
我们肯定是维护一个数据结构,然后来去除掉一些我们不需要的信息。那么看看下图所示的情况:
如图所示,红线(a)和黑线(b)是已经处理完的直线,然后现在要进行计算的是蓝线(c)
红线和黑线满足于这个关系yb<ya且ka<kb
那么蓝线如果要交黑线,肯定可以交红线,而且交红线可以封闭[ya,yc]这一段区间(别吐槽我区间左右反过来的问题,我是从上往下考虑的),封闭的区间比与黑线交封闭的更大。
那么实际上我们只是需要维护一个序列(栈),满足点对应的直线斜率递减,加入序列的顺序是从y坐标大到小依次加入。
当有一条新直线来的时候,在序列中二分能交到哪,给区间头尾打个标记(相当于差分)。
假如一条都交不到,加入序列(说明这条线斜率是目前最小)
直线左侧做法和右侧是完全一样的,但是判断与右侧相反
最后按顺序扫一下,假如直线两侧对应的区间都是有限,说明这段是有限的,反之无限。
貌似出题人给的方法一点都不友好QwQ
那个如果一个平面是有限的,那么它被分为两部分,这两部分都是有限的。
假设我们要求的那条直线是y轴(不是也可以转),那么考虑对直线左右分别计算平面是否有限。
就直线右侧而言,我们把交点按照顺序排好。交点ya和yb之间的区间对应平面是有限的,当且仅当存在yc和yd,满足yd≤yb≤ya≤yc,且kc<kd。
其中c,d可以是a,b,k代表交点对应直线斜率。
感性认识一下吧……
那么先说一下把要求的直线旋到y轴的原因:好判断啊,一边的直线斜率全是连续的了。但是旋转后平行难判,要用原始坐标判断。
那么考虑一下如何维护相交。
我们肯定是维护一个数据结构,然后来去除掉一些我们不需要的信息。那么看看下图所示的情况:
如图所示,红线(a)和黑线(b)是已经处理完的直线,然后现在要进行计算的是蓝线(c)
红线和黑线满足于这个关系yb<ya且ka<kb
那么蓝线如果要交黑线,肯定可以交红线,而且交红线可以封闭[ya,yc]这一段区间(别吐槽我区间左右反过来的问题,我是从上往下考虑的),封闭的区间比与黑线交封闭的更大。
那么实际上我们只是需要维护一个序列(栈),满足点对应的直线斜率递减,加入序列的顺序是从y坐标大到小依次加入。
当有一条新直线来的时候,在序列中二分能交到哪,给区间头尾打个标记(相当于差分)。
假如一条都交不到,加入序列(说明这条线斜率是目前最小)
直线左侧做法和右侧是完全一样的,但是判断与右侧相反
最后按顺序扫一下,假如直线两侧对应的区间都是有限,说明这段是有限的,反之无限。
#include<stdio.h> #include<cmath> #include<algorithm> #define now e[i].k #define N 100005 #define eps 0.00000000001 using namespace std; bool f ; int l,r,mid,n,d ,t,p ; long double x1 ,Y1 ,x2 ,y2 ,x,y; long long XX1 ,YY1 ,XX2 ,YY2 ; struct mpoi { long double pos; int k; friend bool operator < (mpoi a,mpoi b){return a.pos>b.pos;} }e ; inline void getpoi(const int &i){e[i].pos=Y1[i]-x1[i]*(Y1[i]-y2[i])/(x1[i]-x2[i]);now=i;} inline bool cmp(const int &i,const int &j) { return (XX1[i]-XX2[i])*(YY1[j]-YY2[j])!=(XX1[j]-XX2[j])*(YY1[i]-YY2[i]) && (Y1[i]-y2[i])*(x1[j]-x2[j])<(Y1[j]-y2[j])*(x1[i]-x2[i]); } inline void judge(const int &f) { d[t=1]=1; for (int i=2;i<n;i++) if (f?cmp(e[d[t]].k,now):cmp(now,e[d[t]].k)) { for (l=1,r=t,mid=t+1>>1;l<r;mid=l+r>>1) if (f?cmp(e[d[mid]].k,now):cmp(now,e[d[mid]].k)) r=mid; else l=mid+1; p[e[d[l]+1].k]++;p[e[i+1].k]--; } else d[++t]=i; } int main() { scanf("%d",&n);n++; for (int i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",XX1+i,YY1+i,XX2+i,YY2+i); x1[i]=XX1[i];Y1[i]=YY1[i];x2[i]=XX2[i];y2[i]=YY2[i]; } for (int i=1;i<=n;i++) x2[i]-=x1 ,x1[i]-=x1 ,y2[i]-=Y1 ,Y1[i]-=Y1 ; long double th=atan((Y1 -y2 )/(x1 -x2 ))+3.14159265358979/2; for (int i=1;i<=n;i++) { x=x1[i]*cos(th)+Y1[i]*sin(th); y=Y1[i]*cos(th)-x1[i]*sin(th); x1[i]=x;Y1[i]=y; x=x2[i]*cos(th)+y2[i]*sin(th); y=y2[i]*cos(th)-x2[i]*sin(th); x2[i]=x;y2[i]=y; } for (int i=1;i<n;i++) { if (x2[i]<x1[i]) swap(x1[i],x2[i]),swap(Y1[i],y2[i]); getpoi(i); } sort(e+1,e+n); judge(1); for (int i=1,tag=0;i<=n;p[e[i++].k]=0) if (tag+=p[now]) f[now]=1; judge(0); for (int i=1,tag=0;i<=n;i++) putchar(((tag+=p[now]) && f[now])?'1':'0'); }
相关文章推荐
- UOJ #242. 【UR #16】破坏蛋糕
- UOJ 241. 【UR #16】破坏发射台 [矩阵乘法]
- 【UOJ】#241. 【UR #16】破坏发射台
- [几何] UR #16 B.破坏蛋糕
- [矩阵快速幂 数学] UR #16 A.破坏发射台
- uoj#187. 【UR #13】Ernd
- UOJ #60. 【UR #5】怎样提高智商
- 【UOJ169】【UR #11】元旦老人与数列
- UOJ#152. 【UR #10】汉诺塔
- UOJ#49. 【UR #3】铀仓库
- UOJ【UR #12】实验室外的攻防战
- [UOJ 74] 【UR #6】破解密码
- UOJ#61. 【UR #5】怎样更有力气
- UOJ 133 [UR #9]电路手动分析
- UOJ 21 [UR #1]缩进优化
- 【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)
- UOJ #134(【UR #9】App 管理器-tarjen+构造)
- UOJ 180【UR #12】实验室外的攻防战
- [UOJ]#33. 【UR #2】树上GCD
- uoj #152. 【UR #10】汉诺塔