维护一个斜率的绝对值递增的单调栈,然后正反各搞一遍即可。
#include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque> #include <bitset> #include <list> #include <cstdlib> #include <climits> #include <cmath> #include <ctime> #include <algorithm> #include <stack> #include <sstream> #include <numeric> #include <fstream> #include <functional> using namespace std; #define MP make_pair #define PB push_back typedef long long LL; typedef unsigned long long ULL; typedef vector<int> VI; typedef pair<int, int> PII; typedef pair<double, double> PDD; const int INF = INT_MAX / 3; const double eps = 1e-8; const LL LINF = 1e17; const double DINF = 1e60; const int maxn = 1e5 + 10; const double PI = acos(-1.0); struct Building { double x,h; bool operator < (const Building &b) const { return x < b.x; } }; struct Query { double x,ans; int id; bool operator < (const Query &b) const { return x < b.x; } }; struct Node { double k, outpos, x, h; }; bool cmp(const Query &a, const Query &b) { return a.id < b.id; } Query q[maxn]; Building lou[maxn]; int n,m; stack<Node> stk; void calc(int rev) { while(!stk.empty()) stk.pop(); for(int i = 0, j = 0; i < m; i++) { while(j < n && (lou[j].x < q[i].x) ^ rev) { while(!stk.empty()) { Node now = stk.top(); double nowk = (lou[j].h - now.h) / (lou[j].x - now.x); if(rev) nowk *= -1; if(nowk >= now.k) stk.pop(); else break; } Node nxt; nxt.x = lou[j].x; nxt.h = lou[j].h; if(stk.empty()) { nxt.outpos = rev ? -DINF : DINF; nxt.k = 0; } else { Node now = stk.top(); nxt.k = (nxt.h - now.h) / (nxt.x - now.x); nxt.outpos = nxt.x - nxt.h / nxt.k; if(rev) nxt.k *= -1; } stk.push(nxt); j++; } if(!rev) while(!stk.empty() && (stk.top().outpos < q[i].x)) stk.pop(); else while(!stk.empty() && (stk.top().outpos > q[i].x)) stk.pop(); Node now = stk.top(); q[i].ans += atan(now.h / abs(now.x - q[i].x)); } } int main() { int T; scanf("%d",&T); for(int kase = 1; kase <= T; kase++) { scanf("%d",&n); for(int i = 0;i < n;i++) { scanf("%lf%lf", &lou[i].x, &lou[i].h); } scanf("%d",&m); for(int i = 0;i < m;i++) { scanf("%lf", &q[i].x); q[i].ans = 0; q[i].id = i; } sort(lou, lou + n); sort(q, q + m); calc(false); reverse(lou, lou + n); reverse(q, q + m); calc(true); sort(q, q + m, cmp); printf("Case #%d: ", kase); for(int i = 0;i < m;i++) { printf("%.10f ", 180 - q[i].ans * 180 / PI); } } return 0; }