HDU 4923 Room and Moor——单调栈

1.去掉前缀0和后缀1

2.将剩余的串划分成10串,每一位代表1或者0的个数

3.对于一个10节,b的值是一定的,假设1的数量为x,0的数量为y,那么可以求出一个函数f = x*(1-b)^2+y*b^2,化简后利用一元二次函数求最值的公式可知b取x/(x+y)时函数有最小值xy/(x+y)

4.用单调栈从左到右对每个10节进行遍历,每次比较当前10节的b值和栈顶10节的b值的大小,如果当前10节的b值大于栈顶10节的b值,那么直接将当前的10节入栈,否则弹栈直到当前10节的b值大于栈顶10节的b值,然后将当前的10节入栈。

5.将所有10节弹栈,每次根据公式xy/(x+y)累加结果

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
const int maxn = 1e5 + 10;
const double eps = 1e-8;
int dcmp(double x) {
    if (fabs(x) > eps) return 0;
    return fabs(x) > 0 ? 1 : -1;
}
int T, n, t[maxn], tot, num[maxn];
stack<P> s;

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &t[i]);
        tot = 0;
        while (!s.empty()) s.pop();
        int l = 1, r = n;
        for (int i = 1; i <= n && t[i] == 0; i++) l++;
        for (int i = n; i >= 1 && t[i] == 1; i--) r--;
        if (l > r) {
            printf("%.6lf\n", 0.0);
            continue;
        }
        int cnt = 0;
        while (l <= r) {
            ++tot;
            cnt = 0;
            while (l <= r && t[l] == 1) l++, cnt++;
            num[tot] = cnt;
            ++tot;
            cnt = 0;
            while (l <= r && t[l] == 0) l++, cnt++;
            num[tot] = cnt;
        }
        s.push(make_pair(num[1], num[2]));
        for (int i = 3; i <= tot; i += 2) {
            int x = s.top().first, y = s.top().second;
            if (1.0*num[i]/(num[i]+num[i+1]) >= 1.0*x/(x+y)) s.push(make_pair(num[i], num[i+1]));
            else {
                int xx = num[i], yy = num[i+1];
                while (1.0*xx/(xx+yy) < 1.0*x/(x+y)) {
                    xx += x, yy += y;
                    s.pop();
                    if (s.empty()) break;
                    x = s.top().first, y = s.top().second;
                }
                s.push(make_pair(xx, yy));
            }
        }
        double ans = 0;
        while (!s.empty()) {
            int x = s.top().first, y = s.top().second;
            s.pop();
            ans += 1.0*x*y/(x+y);
        }
        printf("%.6lf\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/80052583