Buy low-cost solution to a problem [P1108]

Topic Link

Solution cheap to buy

Title effect: seeking a number of columns of the longest sequence length decreases, and decrease the number of the longest sequence of

Title Analysis: find the longest drop sequence is a routine operation, can be directly used plain \ (O (n ^ 2) \) algorithm, can also be used to achieve binary \ (O (nlogn) \) complexity, but \ ( n \ leq 5000 \) simple algorithm just run

So how statistics program it?

We \ (DP \) find the longest sequence is provided drop \ (d (i) \) represented by \ (I \) the maximum length of the end drop sequence. Similarly, we can use \ (f (i ) \) represented by \ (I \) ends, a length \ (d (i) \) number of drops subsequence

不难想到\(f(i) = \begin{cases} 1 \qquad d(i) == 1 \\ \sum_{j}^{i - 1}\{f(j)\;|\;j < i \;\;\&\&\;\;f(j) + 1 == f(i)\} \end{cases}\)

But doing so is problematic, because of double counting

If there \ (d (i) == d (j) \) and \ (A (I) A == (J) \) , and satisfies I $ <J \ (, have \) F (I) \ Leq f (j) $

The reason is simple, because \ (f (i) \) of all programs are \ (f (j) \) are included, then you will need to \ (f (j) \) is set to \ (0 \) , or \ (f (j) \) program will be counted multiple times

Code offer, data on small-scale write \ (O (n ^ 2) \) algorithm

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 8192;
int val[maxn],g[maxn],d[maxn],f[maxn],n,ans;//val为原数列,d[i]表示以i结尾的最长下降子序列长度,f[i]表示以i结尾,长度为d[i]的下降子序列的数量
int main(){
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1;i <= n;i++)
        cin >> val[i];
    for(int i = 1;i <= n;i++)
        g[i] = -0x7fffffff;
    ans = -1;
    for(int i = 1;i <= n;i++){
        int k = 0;
        int l = 1,r = n;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(g[mid] > val[i])k = mid,l = mid + 1;
            else r = mid - 1;
        }
        d[i] = k + 1;
        g[k + 1] = val[i];
        ans = max(ans,d[i]);
    }
    cout << ans << " ";//求LIS,没啥好说的
    for(int i = 1;i <= n;i++){//依照转移方程
        if(d[i] == 1)f[i] = 1;
        for(int j = 1;j < i;j++)
            if(d[i] == d[j] && val[i] == val[j])//如果j的方案已经被i包含了
                f[j] = 0;
            else if(d[i] == d[j] + 1 && val[i] < val[j])//统计方案
                f[i] += f[j];
    }
    int sum = 0;
    for(int i = 1;i <= n;i++){//输出答案
        if(d[i] == ans)sum += f[i];
    }
    cout << sum << '\n';
    return 0;
}

Guess you like

Origin www.cnblogs.com/colazcy/p/11514975.html