cf Educational Codeforces Round 48 E. Rest In The Shades
原題: E. Rest In The Shades time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output There is a light source on the plane. This source is so small that it can be represented as point. The light source is moving from point (a,sy) to the (b,sy) (sy<0) with speed equal to 1 unit per second. The trajectory of this light source is a straight segment connecting these two points.There is also a fence on OX axis represented as n segments (li,ri) (so the actual coordinates of endpoints of each segment are (li,0)and (ri,0)). The point (x,y) is in the shade if segment connecting (x,y) and the current position of the light source intersects or touches with any segment of the fence.
You are given q points. For each point calculate total time of this point being in the shade, while the light source is moving from (a,sy) to the (b,sy).
Input First line contains three space separated integers sy, a and b (−10^9≤sy<0, 1≤a < b ≤10^9) — corresponding coordinates of the light source. Second line contains single integer n (1≤n≤2⋅10^5) — number of segments in the fence.
Next n lines contain two integers per line: li and ri (1≤li < ri ≤10^9, ri−1< li) — segments in the fence in increasing order. Segments don’t intersect or touch each other.
Next line contains single integer q (1≤q≤2⋅10^5) — number of points to check.
Next q lines contain two integers per line: xi and yi (1≤xi,yi≤10^9) — points to process.
Output Print q lines. The i-th line should contain one real number — total time of the i-th point being in the shade, while the light source is moving from (a,sy) to the (b,sy). The answer is considered as correct if its absolute of relative error doesn’t exceed 10^−6.
Example input -3 1 6 2 2 4 6 7 5 3 1 1 3 6 1 6 4 7 6 output 5.000000000000000 3.000000000000000 0.000000000000000 1.500000000000000 2.000000000000000 Note The 1-st point is always in the shade; the 2-nd point is in the shade while light source is moving from (3,−3) to (6,−3); the 3-rd point is in the shade while light source is at point (6,−3).the 4-th point is in the shade while light source is moving from (1,−3) to (2.5,−3) and at point (6,−3); the 5-th point is in the shade while light source is moving from (1,−3) to (2.5,−3) and from (5.5,−3) to (6,−3);
中文:
給你一個光源,在一條實現上運動,光源運動的直線對面是一個由一些遮擋區間組成平面,平面與光源運動的直線平行,平面背面有一些點,現在問你光源從直線的一端運動到另一端,每個點沒有被光源照到的總時間是多少?
程式碼(題解的程式碼)
#include<bits/stdc++.h>
using namespace std;
#define fore(i, l, r) for(int i = int(l); i < int(r); i++)
#define x first
#define y second
typedef long long li;
typedef long double ld;
typedef pair<li, li> pt;
const int INF = int(1e9);
const li INF64 = li(1e18);
const double EPS = 1e-9;
const int N = 200 * 1000 + 555;
li sy, a, b;
int n, q;
pt s[N], p[N];
inline bool read() {
if(!(cin >> sy >> a >> b))
return false;
assert(cin >> n);
fore(i, 0, n)
assert(scanf("%lld%lld", &s[i].x, &s[i].y) == 2);
assert(cin >> q);
fore(i, 0, q)
assert(scanf("%lld%lld", &p[i].x, &p[i].y) == 2);
return true;
}
int getGE(ld x) {
for(int pos = max(int(lower_bound(s, s + n, pt(li(x), -1)) - s) - 2, 0); pos < n; pos++)
if(x <= s[pos].x)
return pos;
return n;
}
li ps[N];
li getSum(int l, int r) {
li ans = r > 0 ? ps[r - 1] : 0;
ans -= l > 0 ? ps[l - 1] : 0;
return ans;
}
inline void solve() {
fore(i, 0, n) {
ps[i] = s[i].y - s[i].x;
if(i > 0)
ps[i] += ps[i - 1];
}
fore(i, 0, q) {
ld lx = p[i].x + (a - p[i].x) * (ld(p[i].y) / (p[i].y - sy));
ld rx = p[i].x + (b - p[i].x) * (ld(p[i].y) / (p[i].y - sy));
int posL = getGE(lx);
int posR = getGE(rx) - 1;
ld sum = getSum(posL, posR);
if(posL > 0)
sum += max(ld(0.0), s[posL - 1].y - max((ld)s[posL - 1].x, lx));
if(posR >= 0)
sum += max(ld(0.0), min((ld)s[posR].y, rx) - s[posR].x);
sum *= ld(p[i].y - sy) / p[i].y;
printf("%.15f\n", double(sum));
}
}
int main() {
#ifdef _DEBUG
freopen("input.txt", "r", stdin);
int tt = clock();
#endif
cout << fixed << setprecision(15);
if(read()) {
solve();
#ifdef _DEBUG
cerr << "TIME = " << clock() - tt << endl;
tt = clock();
#endif
}
return 0;
}
解答:
點的個數有2×10^5個,線段也有2×10^5,而且光源運動的區間是是10^9,很明顯不能對光源進行處理。只能列舉每個點,考慮能不能把線段處理一下,列舉點的時間複雜度O(n),處理線段的的時間複雜度限制O(logn)以內。
借用官方題解中的一張圖片
列舉每一個點,把點看成光源,可以通過相似三角形計算出它通過照射遮擋平面,那麼在直線ab上對映的總長度就是它所在陰影區的總時間。
先對遮擋線段進行預處理,區間長度累加,判斷圖中A’點在哪個線段上,這裡可以用二分查詢來實現,最後得到區間兩端,計算區間兩端中間的障礙總長度即可。
此題二分精度和查詢精度不好處理,明明知道怎麼做的題,就是WA~~ -_-|||