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~~ -_-|||

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值