#342Div2-625D Babaei and Birthday Cake线段树优化DP

首先要明白一个蛋糕在另一个之上当且仅当序号和体积都比原来的大

然后一维显然可以用sort解决,另一维暴力是n^2显然过不了,考虑优化

不妨按体积排序,然后记录对应的在原序列中的序号,然后扫一遍,每次处理完当前之后,便把这个体积插入线段树中,对应的节点就是在原序列中对应的节点,然后每次用logn做大查询,就是简单的线段树优化DP的问题。

当然,比如树状数组等同样支持区间Max的也能做到

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#define mod 1000000007
#define ll long long
#define rep(i, j, k) for(int i = j; i <= k; i++)

using namespace std;

int n;
ll Max[11 * 100009];
ll f[100009];

struct cadongllas
{
	ll r, h;
	int num;
}a[100009];

ll calc (cadongllas x)
{
	return x.r * x.r * x.h;
}

bool cmp (cadongllas x, cadongllas y)
{
	return ((calc (x) < calc (y)) || (calc (x) == calc (y) && x.num > y.num));
}

void insert (int x, int l, int r, int location, ll sum)
{
	if (location > r || location < l)
		return;
	if (l == r)
	{
		if (l == location)
			Max[x] = sum;
		return;
	}
	int mid = (l + r) >> 1;
	insert (2 * x, l, mid, location, sum);
	insert (2 * x + 1, mid + 1, r, location, sum);
	Max[x] = max (Max[2 * x], Max[2 * x + 1]);
}

ll ask (int x, int l, int r, int location)
{
	if (l > location)
		return 0;
	if (r < location)
		return Max[x];
	if (l == r)
	{
		if (l == location)
			return Max[x];
		else
			return 0;
	}
	int mid = (l + r) >> 1;
	return max (ask (2 * x, l, mid, location), ask (2 * x + 1, mid + 1, r, location));
}

int main ()
{
	scanf ("%d", &n);
	rep (i, 1, n)
		cin >> a[i].r >> a[i].h, a[i].num = i;
	sort (a + 1, a + 1 + n, cmp);
	f[1] = calc (a[1]);
	insert (1, 1, n, a[1].num, f[1]);
	ll ans = 0;
	rep (i, 2, n)
	{
		ll now = ask (1, 1, n, a[i].num - 1) + calc (a[i]);
		insert (1, 1, n, a[i].num, now);
	}
	double Ans;
	Ans = acos (-1.0) * ask (1, 1, n, n);
	printf ("%.9lf\n", Ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值