您的位置:首页 > 其它

USACO 4.3 buylow

2008-08-22 22:03 441 查看
求最长下降子序列,平方的算法就可以过

第二问要求这些子序列的个数,相同的序列不可重复算,也是类似第一个问题的动态规划解法,但要处理重复。

这里注意到一个性质,如果对于两个相同的数,如A[i]和A[j](i<j,),如果以他们结尾的最长下降序列大小相同, 那么在i和j之间一定不存在异于A[i]的数A[k](i<k<j),使得以A[k]结尾的最长下降序列和以A[i]结尾的最长下降序列相同。由反证法很容易证明。

由此,我们可以得到一个算法,每次只处理相同数最右边的一个,具体参考实现的22~30行。另外,此题要用高精度,万恶题。。。

int main()

{

int i, j, k;

freopen("buylow.in", "r", stdin);

freopen("buylow.out", "w", stdout);

scanf("%d",&n);

for(i = 1; i <= n; i++) scanf("%d",&a[i]);

a[0] = INT_MAX;

int best = 1; d[1] = 1;

for(i = 2; i <= n; i++){

d[i] = 1;

for(j = 1; j < i; j++)

if(a[j] > a[i]) d[i] = max(d[i], d[j] + 1);

best = max(best, d[i]);

}

cnt[1] = 1;

for(i = 2; i <= n; i++){

int last = -1;

if(d[i] == 1) { cnt[i] = 1; continue;}

for(j = i - 1; j >= 1; j--)

{

if(d[j] == d[i]-1 && a[j] > a[i] && a[j] != last){

cnt[i] += cnt[j];

last = a[j];

}

}

}

BigInt ret = 0;

int last = -1;

for(i = n; i >= 1; i--)

{

if(d[i] == best && a[i] != last)

{

ret += cnt[i];

last = a[i];

}

}

cout << best << " " << ret << endl;

scanf("%d",&n);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: