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;
}