CF1167G题解

传送门

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

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

1.正方形与数轴碰撞。

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

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

答案就是 \(\arctan \dfrac{1}{d}\) 。

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

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

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

结合下图和上图我们可以推出,当 \(\left|d1-d2\right|\leqslant1\) 时两个正方形会相交在顶点上,这时答案为 \(2\times\arctan \dfrac{1}{\max(d1,d2)}\) 。

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

对于情况一,我们可以通过双指针 \(O(n)\) 求出所有答案。但对于情况二,我们考虑到情况一的答案最小为 \(\arctan \dfrac{1}{3500}\) ,这时情况二里 \(\max(d1,d2)\) 为 \(7000\) ,也就是说要向两侧找最多 \(7000\) 个点,直接暴力找是 \(O(md)\) 的,过不了,但我们可以用 bitset 来维护每个询问点左右两侧 d 个点上是否有正方形,这样就可以把复杂度降到 \(O(\dfrac{nd}{w}+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++;
}
}
}

CF1167G题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. java8中CompletableFuture异步处理超时

    java8中CompletableFuture异步处理超时的方法 Java 8 的 CompletableFuture 并没有 timeout 机制,虽然可以在 get 的时候指定 timeout,但 ...

  2. 如何用jupyter打开代码并租用服务器进行运行

    1.启用环境并打开项目 s1:打开anaconda,进入到anaconda prompt命令窗口: s2:(我的代码是pytorch,所以我的环境也是pytorch) a.激活环境:conda act ...

  3. STM32cubemx-HAL库串口断线问题

    STM32cubemx:version5.1 Chip: STM32F446RE IDE:Keil5 Q:小项目上写了个简单的通信包,波特率230400,数据量较大1600Byte/s,DMA的方式实 ...

  4. C#textbox控件区分扫码枪输入和键盘输入

    前言: 一般我们在某个UI界面输入内容的时候又不想人为的去键盘输入,这个时候就需要区分键盘输入和扫码枪的输入,从而禁止人为键盘输入内容,只能使用扫码枪扫码输入.就目前来说这种直插式扫码枪输入和键盘输入 ...

  5. jmeter 压测的执行步骤步骤

    一.设置测试参数 如图 Number of Threads:总共起多少个线程. Ramp-UP Period(in seconds):多少秒启动完所有线程. loop Count:循环次数 Sched ...

  6. 用bcftools将多个vcf文件合并成一个vcf文件 或将多个vcf和合并成的vcf文件拆分成单个样本的vcf文件

    1. 软件的安装 a. bcftools 的安装 b. bgzip的安装: https://blog.csdn.net/weixin_30471065/article/details/95108525 ...

  7. P1138 第 k 小整数

    P1138 第 k 小整数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) dalao 勿喷,适合新手 思路就是排序加查重,最后判断第k小数.思路十分简单. 刚开始我一直想二维循环查 ...

  8. WebService基本功能接口实现

    一.web服务的创建 1.新建一个web服务 创建一个空的模板可以为后面添加服务 2.创建一个服务 3.创建好服务后可以在websevice里面添加一个接口方法 4.我们运行下我们写的简单接口方法是否 ...

  9. Jmeter检查点

    一.Response Assertion(响应断言) 1. 添加响应断言 对Web请求的响应结果进行验证,Response Assertion配置参数 2. 输入需要匹配的字符串 此处对于访问Baid ...

  10. tf.keras.layers.MaxPool2D 简介

    tf.keras.layers.Max2D( pool_size=(2, 2), strides=None, padding='valid', data_format=None ) pool_size ...