hdu 5406 CRB and Apple(树状数组+dp)

题目链接:hdu 5406 CRB and Apple


将树按照高度从大到小排序,高度相同的美味值小的放前面。然后高度值就没有用了,等于说对得到的美味值序列求两个不相交的LIS,使得长度和尽量长。对序列元素离散化后,dp[i][j]表示说两个序列的终止位置分别为i,j的最大长度。从左向右考虑每个美味值,复杂度o(n)。对于一个值c,更新dp数组,枚举第一维状态i,复杂度o(n)。dp[i][c] = dp[c][i] = max(dp[i][j] | j < c),o(n),但是这里可以用树状数组或是其他数据结构,优化到log(n)。注意不能边枚举变修改,会对答案造成影响。


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
#define lowbit(x) ((x)&(-x))
const int maxn = 1005;

struct Item {
	int h, d;
	bool operator < (const Item& u) const { return h > u.h || (h == u.h && d < u.d); }
}P[maxn];

int N, M, idx[maxn], top, fenw[maxn][maxn];

void add (int* f, int x, int w) {
	while (x < maxn) {
		f[x] = max(f[x], w);
		x += lowbit(x);
	}
}

int find(int* f, int x) {
	int ret = 0;
	while (x) {
		ret = max(ret, f[x]);
		x -= lowbit(x);
	}
	return ret;
}

void init () {
	scanf("%d", &N);
	memset(fenw, 0, sizeof(fenw));
	for (int i = 0; i < N; i++) {
		scanf("%d%d", &P[i].h, &P[i].d);
		idx[i] = P[i].d;
	}
	sort(P, P + N);

	top = 1;
	sort(idx, idx + N);
	for (int i = 1; i < N; i++) {
		if (idx[i] == idx[top-1]) continue;
		idx[top++] = idx[i];
	}
	for (int i = 0; i < N; i++)
		P[i].d = lower_bound(idx, idx + top, P[i].d) - idx + 1;
}

int solve () {
	int ans = 0, tmp[maxn];
	for (int i = 0; i < N; i++) {
		int v = P[i].d;
		for (int j = 0; j <= top; j++)
			tmp[j] = find(fenw[j], v + 1) + 1;
		for (int j = 0; j <= top; j++) {
			ans = max(ans, tmp[j]);
			add(fenw[j], v + 1, tmp[j]);
			add(fenw[v], j + 1, tmp[j]);
		}
	}
	return ans;
}

int main () {
	int cas;
	scanf("%d", &cas);
	while (cas--) {
		init ();
		printf("%d\n", solve());
	}
	return 0;
}


你可能感兴趣的:(hdu 5406 CRB and Apple(树状数组+dp))