Air defense training adapted from BZOJ3165 (Line Tree Permanent Marker)

Keywords: Session less

Training of Air Defense

256MB / 1s ; defense.cpp / c / pas / in / out

[Title Description]
Autumn Moon is very good at air combat. Nevertheless, the necessary training should not be slackened.
In a training session, there will be m events.
1. An aircraft appears on the line from (x1,y1) to (x2,y2) and flies back and forth.
2. Autumn month received instructions to crash an aircraft passing through a flight route at coordinate x.
In order to ensure the most likely crash, the aircraft with the lowest altitude at position x will be chosen in autumn.
Because it's just a training mission, the autumn moon won't really crash the plane. You just need to tell her the y coordinates of the lowest aircraft every time you receive an instruction.

[Input Format]
The first line is an integer m, representing the number of events.
Next m lines, each line has several positive integers, and the first number D represents the event type.
If D=1, it means that there is an aircraft, and then there are four positive integers x1,y1,x2,y2.
If D=2, the next positive integer a indicates that in autumn the lowest altitude of an aircraft that can crash at x=a is asked.

[Output Format]
For each query operation, a real number is output to represent the y coordinates of the aircraft. Make sure there are such planes.

[Sample data]
defense1.in
4
1 1 1 3 3
2 3
1 1 3 3 1
2 3
defense1.out
3
1
defense2.in
7
1 3 6 5 7
1 6 1 9 7
1 1 3 7 7
2 3
2 7
1 5 2 10 4
2 7
defense2.out
4.333333
3
2.8

[Data Scope]
For 30% of the data, m is less than 5000.
For the other 30% data, 1 < x,y,a < 100000.
For 100% data, 1 < m < 200000, 1 < x,y,a < 10 ^ 9, x1 < x2.
[Scoring method]
This topic has a custom checker. When the absolute error between your answer and the standard answer does not exceed 1e-4, it is considered correct.

Train of thought:
The segment tree maintains the segment, and updates the segment which can judge the minimum segment of the whole directly, otherwise it will be processed recursively. Processing to a node of length 1 stops. Permanent tag, when querying, we need to consider the tags of all nodes on the path, and take the minimum value.
Actually, it's almost the same as BZOJ3165. It's just to find the smallest y. It's not compulsory online.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define LL long long
#define inf 1000000000
#define N 200010
using namespace std;

int m, root, tot=1;
const double eps=1e-8;

struct Edge{
    int lson, rson;
    double ly, ry;
}tree[N*30];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

inline double get(int x, int X1, double Y1, int X2, double Y2){//The abscissa on the line segment isxHoury 
    return (Y2-Y1) * (x-X1) / (X2-X1) + Y1;
}

int modify(int pos, int l, int r, int x1, double y1, int x2, double y2){
    if ( !pos ){
        pos = ++tot;
        tree[pos].ly = tree[pos].ry = inf;
    }
    int mid = (l + r) >> 1;
    if (x1 <= l && x2 >= r){//The line segment covers the whole interval. 
        double ly = get(l, x1, y1, x2, y2), ry = get(r, x1, y1, x2, y2);
        double sl = ly - tree[pos].ly, sr = ry - tree[pos].ry;
        if (sl<=eps && sr<=eps){//Lower maintenancey 
            tree[pos].ly = ly;
            tree[pos].ry = ry;
            return pos;
        }
        if (sl>=-eps && sr>=-eps)
            return pos;
        //-----------------------------------------------------Interlaced segment
        if (fabs(sl) < fabs(sr)){//From similar triangles, the intersection points can be obtained in the left interval. 
            if (sr <= eps){
                tree[pos].lson = modify(tree[pos].lson, l, mid, l, tree[pos].ly, r, tree[pos].ry);//Recursive Processing Left Interval 
                tree[pos].ly = ly;
                tree[pos].ry = ry;//The current interval is equivalent to the right interval (update), so there is no need to add the right interval. 
            } 
            else
                tree[pos].lson = modify(tree[pos].lson, l, mid, x1, y1, x2, y2);
        } 
        else {//Ditto 
            if (sl <= eps){
                tree[pos].rson = modify(tree[pos].rson, mid+1, r, l, tree[pos].ly, r, tree[pos].ry);
                tree[pos].ly = ly;
                tree[pos].ry = ry;
            } 
            else
                tree[pos].rson = modify(tree[pos].rson, mid+1, r, x1, y1, x2, y2);
        }
    }
    else {
        if (x1 <= mid)
            tree[pos].lson = modify(tree[pos].lson, l, mid, x1, y1, x2, y2);
        if (x2 > mid)
            tree[pos].rson = modify(tree[pos].rson, mid+1, r, x1, y1, x2, y2);
    }
    return pos;
}

double query(int pos, int l, int r, int x){
    if ( !pos ) return inf;
    if ( l == r ) return tree[pos].ly;
    int mid = (l + r) >> 1;
    double ans = get(x, l, tree[pos].ly, r, tree[pos].ry);
    if (x <= mid)//Recursive left and right intervals 
        return min(ans, query(tree[pos].lson, l, mid, x));
    else
        return min(ans, query(tree[pos].rson, mid+1, r, x));
}

int main(){
    freopen ("defense.in", "r", stdin);
    freopen ("defense.out", "w", stdout);
    m = read();
    int x1, x2;
    double y1, y2;
    root = 1;
    tree[root].ly = tree[root].ry = inf;
    while ( m-- ){
        x1 = read();
        if (x1 == 1){
            x1 = read(); y1 = read(); x2 = read(); y2 = read();
            modify(root, 1, inf, x1, y1, x2, y2);
        }
        else {
            x1 = read();
            printf("%.10f\n", query(root, 1, inf, x1));
        }
    }
    return 0;
}

Posted by zipadee on Mon, 20 May 2019 15:47:56 -0700