1. 程式人生 > >洛谷1970 花匠(DP)

洛谷1970 花匠(DP)

題意

找一個高低迴圈的最長XX序列。

題解

DP 設f[i]表示以i為結尾的最長XX序列,其中i在高位。 設g[i]表示以i為結尾的最長XX序列,其中i在低位。 這兩個可以相互轉移,即f[i]=max_{i>j,a[i]>a[j]}{g[j]}+1,同樣g也有一個轉移方程。 接下來用樹狀陣列維護一下max就可以得到50分了。

如何優化呢? 更改一下定義: 設f[i]表示前i個數字中的最長XX序列,其中i在高位。 設g[i]表示前i個數字中的最長XX序列,其中i在低位。 這樣轉移就方便很多了,f[i]=f[i-1]或者f[i]=g[i-1]+1(前提:a[i]>a[i-1]),g同理。

總結

把狀態籠統一些的表達出來(即範圍更廣),那麼轉移會更加方便。

程式碼

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; 
const int maxn=100010;

int n;
int a[maxn];
int f[maxn],g[maxn]; 

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    f[1]=g[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>a[i-1]) f[i]=g[i-1]+1;
        else f[i]=f[i-1];
        if(a[i]<a[i-1]) g[i]=f[i-1]+1;
        else g[i]=g[i-1];
    }
    printf("%d\n",max(f[n],g[n]));
    return 0;
}