以下AC:
#include<bits/stdc++.h>
// #define __float128 long double
namespace std{
__float128 abs(__float128 x){
return x >= 0 ? x : -x;
}
}
std::ostream& operator<<(std::ostream&out, const __float128&x){
return out<<static_cast<long double>(x);
}
namespace Basis2D{
constexpr double PI = acosl(-1.L);
constexpr double INF = 1e8;
constexpr double EPS = 1e-20;
struct Point{
__float128 x,y;
Point(__float128 _x=0, __float128 _y=0):x(_x),y(_y){}
Point& operator=(const Point&o){
x = o.x; y = o.y;
return *this;
}
friend bool operator<(const Point& a, const Point&b){
return std::abs(a.x-b.x)<EPS?a.y<b.y:a.x<b.x;
}
friend Point operator+(const Point& a, const Point&b){
return {a.x+b.x, a.y+b.y};
}
friend Point operator-(const Point&p){
return {-p.x, -p.y};
}
friend Point operator-(const Point& a, const Point&b){
return a + (-b);
}
friend __float128 operator*(const Point& a, const Point&b){
return a.dot(b);
}
__float128 norm()const{
return std::hypotl(x, y);
}
__float128 dot(const Point&o)const{
return x*o.x + y*o.y;
}
__float128 cross(const Point&o)const{
return x*o.y - y*o.x;
}
__float128 theta()const{
return std::abs(x)+std::abs(y)>EPS?atan2l(y,x):-INF;
}
};
using Points = std::vector<Point>;
__float128 norm(const Point&p){
return p.norm();
}
__float128 dot(const Point&a, const Point&b){
return a.dot(b);
}
__float128 cross(const Point&a, const Point&b){
return a.cross(b);
}
__float128 theta(const Point&p){
return p.theta();
}
struct Line : public std::array<Point,2>{
using std::array<Point,2>::array;
Line(Point a, Point b):array({a,b}){}
operator Point()const{
return (*this)[1] - (*this)[0];
}
friend Point operator&(const Line&a, const Line&b){
return a.intersection(b);
}
Point intersection(const Line&o)const{
__float128 S1 = cross(o[1]-(*this)[0], *this);
__float128 S2 = cross(o[0]-(*this)[0], *this);
return Point{
(S1 * o[0].x - S2 * o[1].x) / (S1 - S2),
(S1 * o[0].y - S2 * o[1].y) / (S1 - S2)
};
}
};
using Lines = std::vector<Line>;
Point intersection(const Line&a, const Line&b){
return a.intersection(b);
}
}
namespace Algorithm2D{
using namespace Basis2D;
namespace HalfPlane{
template<typename LineContainer>
Points overlap(const LineContainer&_lines){
Lines lines(_lines.begin(), _lines.end());
std::sort(lines.begin(), lines.end(), [](auto a,auto b){
return theta(a) < theta(b);
});
if(lines.empty() || norm(lines[0]) < EPS) return {};
std::deque<Point> res;
std::deque<Line> dq;
for(auto l : lines){
while(!res.empty() && cross(l, res.back() - l[0]) < -EPS){
res.pop_back(); dq.pop_back();
}
while(!res.empty() && cross(l, res.front() - l[0]) < -EPS){
res.pop_front(); dq.pop_front();
}
dq.push_back(l);
if(dq.size()>1){
if(std::abs(cross(dq.back(), dq[dq.size()-2])) < EPS){
Line bk = dq.back(); dq.pop_back();
if(cross(bk, dq.back()[0] - bk[0]) < -EPS){
if(dot(bk, dq.back()) < -EPS) return {};
dq.back() = l;
}
if(!res.empty()) res.pop_back();
}
if(dq.size()>1) res.push_back(intersection(dq.back(), dq[dq.size()-2]));
}
}
while(!res.empty() && cross(dq.front(), res.back() - dq.front()[0]) < -EPS){
res.pop_back(); dq.pop_back();
}
if(dq.size()>1) res.push_front(intersection(dq.back(), dq.front()));
assert(res.size() >= 3 && cross(dq.front(), dq.back()) <= EPS);
return Points(res.begin(), res.end());
}
}
}
using namespace std;
signed main(){
using namespace Basis2D;
int n, m;cin>>n>>m;
Lines lines;
lines.emplace_back(Point{-INF,-INF},Point{INF,-INF});
lines.emplace_back(Point{INF,-INF},Point{INF,INF});
lines.emplace_back(Point{INF,INF},Point{-INF,INF});
lines.emplace_back(Point{-INF,INF},Point{-INF,-INF});
for(int i=0;i<n;i++){
int a, b, c; cin>>a>>b>>c;
lines.emplace_back(Point{0,1.L*(__float128)c/b}, Point{0,1.L*(__float128)c/b}+Point{1,-1.L*(__float128)a/b});
}
auto poly = Algorithm2D::HalfPlane::overlap(lines);
n = poly.size();
vector<tuple<int, int, int>> query(m);
vector<__float128> ans(m);
for(int i=0; i<m; i++){
int a, b; cin>>a>>b;
query[i] = {a, b, i};
}
sort(query.begin(), query.end(), [](auto x, auto y){
auto[a1,b1,_1] = x;
auto[a2,b2,_2] = y;
// {0,0} -> {b,-a}
return atan2l(-a1,b1) < atan2l(-a2,b2);
});
for(int i=0,j=0; j<m; i=(i+1)%n){
while(true){
auto[a,b,id] = query[j];
auto[x,y] = (poly[(i+1)%n]-poly[i]);
if(x < 0) x=-x, y=-y;
if((__float128)y*b >= -(__float128)a*x + EPS) break;
i = (i+1)%n;
}
while(j<m){
auto[a,b,id] = query[j];
auto[x,y] = (poly[(i+1)%n]-poly[i]);
if(x < 0) x=-x, y=-y;
if((__float128)y*b + EPS < -(__float128)a*x) break;
ans[id] = (__float128)a*poly[i].x + (__float128)b*poly[i].y;
j++;
}
}
cout<<fixed<<setprecision(5);
for(int i=0; i<m; i++){
if(ans[i] < -EPS){
cout<<"IMPOSSIBLE\n";
continue;
}
if(std::abs(ans[i])<EPS) ans[i] = 0.;
cout<<ans[i]<<'\n';
}
return 0;
}
将3~13行的注释得到的WA:
#include<bits/stdc++.h>
#define __float128 long double
// namespace std{
// __float128 abs(__float128 x){
// return x >= 0 ? x : -x;
// }
// }
// std::ostream& operator<<(std::ostream&out, const __float128&x){
// return out<<static_cast<long double>(x);
// }
namespace Basis2D{
constexpr double PI = acosl(-1.L);
constexpr double INF = 1e8;
constexpr double EPS = 1e-20;
struct Point{
__float128 x,y;
Point(__float128 _x=0, __float128 _y=0):x(_x),y(_y){}
Point& operator=(const Point&o){
x = o.x; y = o.y;
return *this;
}
friend bool operator<(const Point& a, const Point&b){
return std::abs(a.x-b.x)<EPS?a.y<b.y:a.x<b.x;
}
friend Point operator+(const Point& a, const Point&b){
return {a.x+b.x, a.y+b.y};
}
friend Point operator-(const Point&p){
return {-p.x, -p.y};
}
friend Point operator-(const Point& a, const Point&b){
return a + (-b);
}
friend __float128 operator*(const Point& a, const Point&b){
return a.dot(b);
}
__float128 norm()const{
return std::hypotl(x, y);
}
__float128 dot(const Point&o)const{
return x*o.x + y*o.y;
}
__float128 cross(const Point&o)const{
return x*o.y - y*o.x;
}
__float128 theta()const{
return std::abs(x)+std::abs(y)>EPS?atan2l(y,x):-INF;
}
};
using Points = std::vector<Point>;
__float128 norm(const Point&p){
return p.norm();
}
__float128 dot(const Point&a, const Point&b){
return a.dot(b);
}
__float128 cross(const Point&a, const Point&b){
return a.cross(b);
}
__float128 theta(const Point&p){
return p.theta();
}
struct Line : public std::array<Point,2>{
using std::array<Point,2>::array;
Line(Point a, Point b):array({a,b}){}
operator Point()const{
return (*this)[1] - (*this)[0];
}
friend Point operator&(const Line&a, const Line&b){
return a.intersection(b);
}
Point intersection(const Line&o)const{
__float128 S1 = cross(o[1]-(*this)[0], *this);
__float128 S2 = cross(o[0]-(*this)[0], *this);
return Point{
(S1 * o[0].x - S2 * o[1].x) / (S1 - S2),
(S1 * o[0].y - S2 * o[1].y) / (S1 - S2)
};
}
};
using Lines = std::vector<Line>;
Point intersection(const Line&a, const Line&b){
return a.intersection(b);
}
}
namespace Algorithm2D{
using namespace Basis2D;
namespace HalfPlane{
template<typename LineContainer>
Points overlap(const LineContainer&_lines){
Lines lines(_lines.begin(), _lines.end());
std::sort(lines.begin(), lines.end(), [](auto a,auto b){
return theta(a) < theta(b);
});
if(lines.empty() || norm(lines[0]) < EPS) return {};
std::deque<Point> res;
std::deque<Line> dq;
for(auto l : lines){
while(!res.empty() && cross(l, res.back() - l[0]) < -EPS){
res.pop_back(); dq.pop_back();
}
while(!res.empty() && cross(l, res.front() - l[0]) < -EPS){
res.pop_front(); dq.pop_front();
}
dq.push_back(l);
if(dq.size()>1){
if(std::abs(cross(dq.back(), dq[dq.size()-2])) < EPS){
Line bk = dq.back(); dq.pop_back();
if(cross(bk, dq.back()[0] - bk[0]) < -EPS){
if(dot(bk, dq.back()) < -EPS) return {};
dq.back() = l;
}
if(!res.empty()) res.pop_back();
}
if(dq.size()>1) res.push_back(intersection(dq.back(), dq[dq.size()-2]));
}
}
while(!res.empty() && cross(dq.front(), res.back() - dq.front()[0]) < -EPS){
res.pop_back(); dq.pop_back();
}
if(dq.size()>1) res.push_front(intersection(dq.back(), dq.front()));
assert(res.size() >= 3 && cross(dq.front(), dq.back()) <= EPS);
return Points(res.begin(), res.end());
}
}
}
using namespace std;
signed main(){
using namespace Basis2D;
int n, m;cin>>n>>m;
Lines lines;
lines.emplace_back(Point{-INF,-INF},Point{INF,-INF});
lines.emplace_back(Point{INF,-INF},Point{INF,INF});
lines.emplace_back(Point{INF,INF},Point{-INF,INF});
lines.emplace_back(Point{-INF,INF},Point{-INF,-INF});
for(int i=0;i<n;i++){
int a, b, c; cin>>a>>b>>c;
lines.emplace_back(Point{0,1.L*(__float128)c/b}, Point{0,1.L*(__float128)c/b}+Point{1,-1.L*(__float128)a/b});
}
auto poly = Algorithm2D::HalfPlane::overlap(lines);
n = poly.size();
vector<tuple<int, int, int>> query(m);
vector<__float128> ans(m);
for(int i=0; i<m; i++){
int a, b; cin>>a>>b;
query[i] = {a, b, i};
}
sort(query.begin(), query.end(), [](auto x, auto y){
auto[a1,b1,_1] = x;
auto[a2,b2,_2] = y;
// {0,0} -> {b,-a}
return atan2l(-a1,b1) < atan2l(-a2,b2);
});
for(int i=0,j=0; j<m; i=(i+1)%n){
while(true){
auto[a,b,id] = query[j];
auto[x,y] = (poly[(i+1)%n]-poly[i]);
if(x < 0) x=-x, y=-y;
if((__float128)y*b >= -(__float128)a*x + EPS) break;
i = (i+1)%n;
}
while(j<m){
auto[a,b,id] = query[j];
auto[x,y] = (poly[(i+1)%n]-poly[i]);
if(x < 0) x=-x, y=-y;
if((__float128)y*b + EPS < -(__float128)a*x) break;
ans[id] = (__float128)a*poly[i].x + (__float128)b*poly[i].y;
j++;
}
}
cout<<fixed<<setprecision(5);
for(int i=0; i<m; i++){
if(ans[i] < -EPS){
cout<<"IMPOSSIBLE\n";
continue;
}
if(std::abs(ans[i])<EPS) ans[i] = 0.;
cout<<ans[i]<<'\n';
}
return 0;
}