CodeForces 629D Babaei and Birthday Cake

最长上升序列变形。LIS线段树写法。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxn = 100000 + 10;
struct X
{
    long long r, h;
    int id;
}s[maxn];
int n;
long long MAX[4 * maxn];
long long ans;
long long f[maxn];
long long pri;
double pi = acos(-1.0);

bool cmp(const X&a, const X&b)
{
    if (a.r*a.r*a.h == b.r*b.r*b.h) return a.id>b.id;
    return a.r*a.r*a.h<b.r*b.r*b.h;
}

void read()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d%d", &s[i].r, &s[i].h);
        s[i].id = i;
    }
}

void pushUp(int rt)
{
    MAX[rt] = max(MAX[2 * rt], MAX[2 * rt + 1]);
}

void build(int l, int r, int rt)
{
    if (l == r)
    {
        MAX[rt] = 0;
        return;
    }
    int m = (l + r) / 2;
    build(l, m, 2 * rt);
    build(m + 1, r, 2 * rt + 1);
    pushUp(rt);
}

void quary(int L, int R, int l, int r, int rt)
{
    if (L <= l&&r <= R)
    {
        ans = max(ans, MAX[rt]);
        return;
    }

    int m = (l + r) / 2;
    if (L <= m) quary(L, R, l, m, 2 * rt);
    if (R >= m + 1) quary(L, R, m + 1, r, 2 * rt + 1);
}

void update(int pos, int l, int r, int rt)
{
    if (l == r)
    {
        MAX[rt] = ans;
        return;
    }

    int m = (l + r) / 2;
    if (pos <= m) update(pos, l, m, 2 * rt);
    if (pos>m) update(pos, m + 1, r, 2 * rt + 1);
    pushUp(rt);
}

void work()
{
    build(1, n, 1);
    sort(s + 1, s + 1 + n, cmp);
    pri = 0;
    for (int i = 1; i <= n; i++)
    {
        ans = 0;
        quary(1, s[i].id, 1, n, 1);
        ans = s[i].r*s[i].r*s[i].h + ans;
        update(s[i].id, 1, n, 1);
        pri = max(pri, ans);
    }
//    printf("%lld
", pri);
    printf("%.10lf
", (double)pri*pi);
}

int main()
{
    read();
    work();
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5208951.html