POJ1952BUY LOW, BUY LOWER题解动态规划DP

BUY LOW, BUY LOWER
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 4652 Accepted: 1563

Description

The advice to "buy low" is half the formula to success in the bovine stock market.To be considered a great investor you must also follow this problems' advice:
                    "Buy low; buy lower"

Each time you buy a stock, you must purchase it at a lower price than the previous time you bought it. The more times you buy at a lower price than before, the better! Your goal is to see how many times you can continue purchasing at ever lower prices.

You will be given the daily selling prices of a stock (positive 16-bit integers) over a period of time. You can choose to buy stock on any of the days. Each time you choose to buy, the price must be strictly lower than the previous time you bought stock. Write a program which identifies which days you should buy stock in order to maximize the number of times you buy.

Here is a list of stock prices:
 Day   1  2  3  4  5  6  7  8  9 10 11 12

Price 68 69 54 64 68 64 70 67 78 62 98 87


The best investor (by this problem, anyway) can buy at most four times if each purchase is lower then the previous purchase. One four day sequence (there might be others) of acceptable buys is:
Day    2  5  6 10

Price 69 68 64 62

Input

* Line 1: N (1 <= N <= 5000), the number of days for which stock prices are given

* Lines 2..etc: A series of N space-separated integers, ten per line except the final line which might have fewer integers.

Output

Two integers on a single line:
* The length of the longest sequence of decreasing prices
* The number of sequences that have this length (guaranteed to fit in 31 bits)

In counting the number of solutions, two potential solutions are considered the same (and would only count as one solution) if they repeat the same string of decreasing prices, that is, if they "look the same" when the successive prices are compared. Thus, two different sequence of "buy" days could produce the same string of decreasing prices and be counted as only a single solution.

Sample Input

12
68 69 54 64 68 64 70 67 78 62
98 87

Sample Output

4 2

Source

经典的LIS问题,关键是求不重复的子串数量
DP时多求了一个为了记录前面不重复的子串数量
O(nlogn)算法
设原来的序列为A[],不失一般性,我们只考虑严格递增的情况(原题是递减)
用L[i]表示以A[i]结尾的LIS的长度
用cnt[i]纪录以A[i]结尾的且长度为L[i]的本质不同的LIS的数量,首先用nlogn的算法计算出所有元素的L值
然后依次扫描A[1],A[2],……A[n],每扫一个元素,就统计该元素的cnt的值,然后把元素插入到一个list链表中
list[k]只保存L值为k的元素,list[k]中的元素按升序排列(相同元素只保留一个),一共有n个list。

例如对于序列,1,5,3,2,6

list[1]:1
list[2]:2,3,5
list[3]: 6

此时如果扫描到一个4,那么显然该元素的L值为3。
也就是说4应该插入list[3]中。在插入之前必须先统计以元素4的cnt值。
计算这个cnt值的方法如下:在list[2]中找到第一个比4小的元素i(例子中就是3),那么从表头元素到i的所有元素的cnt总和就是4的cnt值。
关键在于如何快速找到list[2]中第一个比4小的元素,我们只要纪录一个pos指针,初始化的时候pos指向链表最末尾元素,查找的过程相当于向左移动指针的过程,直到遇到一个比4小的元素。如果下次仍然是在list[2]中查找,那么只要从pos开始往前查找即可(想想为什么不用从尾元素开始)。

得到以4结尾的cnt值后,再把4插入到list[3]中,由于4一定是最小的元素(想想为什么),所以一定是头插入。

最后要注意的是如果list[k]有两个元素相同,只留下一个。

注:L[i]需要在扫描前就计算出来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值