0%

CF 1016E Rest In The Shades

题意

有一个光源在x轴下方且平行于x轴的某条线段AB上作匀速直线运动,x轴上有n($$1 <= n <= 210^5$$)条会阻挡光线的线段,现在有q($$1 <= n <= 210^5$$)个在x轴上方的点,问这q个点没有被光线照射到的时间分别是多少。

分析

经过观察发现,到达某个点的光假如会被多条线段阻挡,那么这些线段大部分是完整且相邻的,最多只有两条线段是不完整的,因此,我们可以用前缀和来处理完整的线段,然后用二分搜索来处理不完整的线段,求和。接着,由相似三角形的相关定理可计算出在x轴上线段在AB上投影,进而求得答案。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include<bits/stdc++.h>
#define x first
#define y second
#define ok cout << "ok" << endl;
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const double PI = acos(-1.0);
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const int N=2e5+9;
const double Eps=1e-7;

double sum[N];
int n, l, r, q, x, y, vis, idx1, idx2;
double sy, xa, xb;

struct node {
double l, r, id;
node() {}
node(double l, double r, int id): l(l), r(r), id(id) {}
bool operator < (const node &rhs) const {
if(l != rhs.l) return l < rhs.l;
if(r != rhs.r) return r < rhs.r;
return id < rhs.id;
}
};

set<node> se;

int main(void) {
if(fopen("in", "r")!=NULL) {freopen("in", "r", stdin); freopen("out", "w", stdout);}
while(~scanf("%lf%lf%lf", &sy, &xa, &xb)) {
scanf("%d", &n);
sum[0] = 0;
for(int i = 1; i <= n; i++) {
scanf("%d%d", &l, &r);
sum[i] = sum[i-1] + r - l;
se.insert(node(l, r, i));
}
scanf("%d", &q);
while(q--) {
scanf("%d%d", &x, &y);
double ans = 0;
double x1 = (y * xa - sy * x) / (y - sy);
double x2 = (y * xb - sy * x) / (y - sy);
auto it = se.lower_bound(node(x1, -1, -1));
vis = -1;
idx1 = (it == se.end() ? INF : it->id);
if(it != se.begin()) {
it--;
if(x1 < it->r) {
ans += min(it->r, x2) - x1;
vis = it->id;
}
}
it = se.lower_bound(node(x2, -1, -1));
if(it != se.begin()) {
it--;
if(x2 < it->r && vis != it->id) {
ans += x2 - max(it->l, x1);
}
if(x2 < it->r) {
if(it != se.begin()) {
it--;
idx2 = it->id;
}
else {
idx2 = -INF;
}
}
else {
idx2 = it->id;
}
}
else {
idx2 = -INF;
}
if(idx1 <= idx2) {
ans += sum[idx2] - sum[idx1-1];
}
ans *= 1.0 * (y - sy) / y;
printf("%.10f\n", ans);
}
}

return 0;
}