CF629D Babaei and Birthday Cake


题意:给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和。

dp[i]=max(dp[j])+v[i](j<i&&v[i]>v[j]);

离散化,线段树维护区间最大值


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {
	public static void main(String[] args) {
		new CF_629D().run();
	}
}

class CF_629D {

	void run() {
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
		int n = cin.nextInt();
		for (int i = 0; i < n; i++) {
			long r = cin.nextLong();
			volume[i] = r * r * cin.nextLong();
		}
		Hash h = new Hash(n, volume);
		int limit = h.length() - 1;
		buildtree(1, 0, limit);
		for (int i = 0; i < n; i++) {
			int idx = h.Idx(volume[i]);
			long premax = ask(0, idx - 1, 1, 0, limit);
			update(idx, premax + volume[i], 1, 0, limit);
		}
		cout.printf("%.9f\n", Math.PI * ask(0, limit, 1, 0, limit));
		cout.flush();
	}

	void buildtree(int t, int l, int r) {
		left[t] = l;
		right[t] = r;
		max[t] = 0;
		if (l == r)
			return;
		int mid = (l + r) >> 1;
		buildtree(t << 1, l, mid);
		buildtree(t << 1 | 1, mid + 1, r);
		up(t);
	}

	void update(int i, long c, int t, int l, int r) {
		if (l == r) {
			max[t] = c;
			return;
		}
		int mid = (l + r) >> 1;
		if (i <= mid)
			update(i, c, t << 1, l, mid);
		else
			update(i, c, t << 1 | 1, mid + 1, r);
		up(t);
	}

	long ask(int al, int ar, int t, int l, int r) {
		if (al > ar)
			return 0L;
		if (al <= l && r <= ar)
			return max[t];
		int mid = (l + r) >> 1;
		long ans = 0L;
		if (al <= mid)
			ans = Math.max(ans, ask(al, ar, t << 1, l, mid));
		if (ar > mid)
			ans = Math.max(ans, ask(al, ar, t << 1 | 1, mid + 1, r));
		return ans;
	}

	void up(int t) {
		max[t] = Math.max(max[t << 1], max[t << 1 | 1]);
	}

	final int N = 100_002;
	long[] volume = new long[N];
	int[] left = new int[N << 2];
	int[] right = new int[N << 2];
	long[] max = new long[N << 2];
}

class Hash {
	Hash(int length, long[] array) {
		Set<Long> st = new TreeSet<Long>();
		for (int i = 0; i < length; i++)
			st.add(array[i]);
		this.array = new long[st.size()];
		size = 0;
		for (long i : st)
			this.array[size++] = i;
	}

	int Idx(long key) {
		return Arrays.binarySearch(array, 0, size, key);
	}

	int length() {
		return size;
	}

	int size;
	long[] array;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值