HDU 5033 Building 单调栈

维护一个斜率的绝对值递增的单调栈,然后正反各搞一遍即可。

#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:\n", kase);
        for(int i = 0;i < m;i++) {
            printf("%.10f\n", 180 - q[i].ans * 180 / PI);
        }
    }
    return 0;
}

 

posted @ 2014-09-23 14:42  acm_roll  阅读(137)  评论(0编辑  收藏  举报