您的位置:首页 > 移动开发

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

2015-08-21 22:23 441 查看
题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: