CF1167G题解

1|0CF1167G题解

传送门

简化题意:数轴上有 n 个不相交且处于坐标为非负整数的单位正方形,给 m 个询问点,求出把这个点右侧的数轴逆时针旋转至与左侧相交时的角度。

首先,碰撞时只能有以下两种情况:

1.正方形与数轴碰撞。

2.正方形与正方形碰撞。

对于第一种情况,我们通过画图就可以很好理解求法:

情况1

答案就是 arctan1d

对于第二中情况,我们可以证明,两个正方形只会在顶点上相交。

情况二

采用反证法,如果两个正方形的交点 A 在其中一个的边上(显然不可能都在边上),那么过 A 向其所在的边所对的正方形的底边作垂线,并连接 A 与旋转中心 M ,我们就可以通过角平分线的性质证明出 AMH 全等于 AMB ,因此 BM=HM ,而 B,M 都是整点,因此 BM 长为整数,所以 HM 长为整数,H 在整点上,这也就证明了交点一定在正方形顶点上。

那满足什么条件时才会在顶点上相交呢?

结合下图和上图我们可以推出,当 |d1d2|1 时两个正方形会相交在顶点上,这时答案为 2×arctan1max(d1,d2)

数学的部分结束了,我们就开始考虑做法。

对于情况一,我们可以通过双指针 O(n) 求出所有答案。但对于情况二,我们考虑到情况一的答案最小为 arctan13500 ,这时情况二里 max(d1,d2)7000 ,也就是说要向两侧找最多 7000 个点,直接暴力找是 O(md) 的,过不了,但我们可以用 bitset 来维护每个询问点左右两侧 d 个点上是否有正方形,这样就可以把复杂度降到 O(ndw+q) ,这样就可以通过此题。

#include<bits/stdc++.h> #define ll long long #define ld long double using namespace std; inline int read(){ int s=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar(); return s; } const int N=200501; const ld pi=acos(-1);//求π int n,d,m,le,ri; ll a[N],q[N]; bitset<7005>l,r,tmp; ld work(int i,int j){ return atan((ld)i/(ld)j); } int main(){ // freopen("travel.in","r",stdin); // freopen("travel.out","w",stdout); n=read(),d=read(); for(int i=1;i<=n;i++)a[i]=read(); m=read(); for(int i=1;i<=m;i++)q[i]=read(); for(int i=1;i<=n&&a[i]<=q[1]+7000;i++){//处理第一个询问点前的情况 if(a[i]>=q[1])r.set(a[i]-q[1]); else{ le=i+1; if(a[i]>=q[1]-7001)l.set(q[1]-a[i]-1); } } for(int i=1;i<=m;i++){ ld ans=0; int pos=0; if(l.test(0)||r.test(0))ans=pi/(ld)2.0; else ans=work(1,min(l._Find_first(),r._Find_first())); tmp=l&r;if(tmp.any())pos=tmp._Find_first(),ans=max(ans,pos?2*work(1,pos):pi);//d1=d2的情况 tmp=(l<<1)&r;if(tmp.any())pos=tmp._Find_first(),ans=max(ans,2*work(1,pos)); tmp=l&(r<<1);if(tmp.any())pos=tmp._Find_first(),ans=max(ans,2*work(1,pos));//|d1-d2|=1的情况 printf("%.15Lf\n",ans); if(i==m)return 0; l<<=(q[i+1]-q[i]),r>>=(q[i+1]-q[i]); while(a[le]<q[i+1]){ if(a[le]>=q[i+1]-7001)l.set(q[i+1]-a[le]-1); le++; } while(a[ri]<=q[i+1]+7000&&ri<=n){ if(a[ri]>=q[i+1])r.set(a[ri]-q[i+1]); ri++; } } }

__EOF__

本文作者Xttttr
本文链接https://www.cnblogs.com/Xttttr/p/17114470.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Xttttr  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示