BZOJ 1049 [HAOI2006]数字序列 DP

第一问:最长xx子序列

第二问:f[i]表示前i个的最少花费,可以从满足条件j(假设以a[i]结尾的最长xx组序列长度为len,则j需要满足以a[j]结尾的最长xx组序列长度为len-1)

方法:记录最长xx子序列的转移,邻接表存,然后枚举每个转移。

ps:有个结论:如果从j转移到i的话,那么中间一定有一个k(k>=j&&k<i),使得j~k的高度都是a[j],k+1~i的高度都是i,且这样的花费是最优的,很容易想明白的~

 

这个暴力显然tle,怎么可能会ac?

数据弱,不解释

View Code
 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <cstdio>

 5 #include <algorithm>

 6 

 7 #define N 55555

 8 #define INF 1LL<<60

 9 

10 using namespace std;

11 

12 int a[N],c[N];

13 int n,cnt,len;

14 int dp[N];

15 int head[N],next[N],to[N];

16 long long f[N],sum1[N],sum2[N];

17 

18 inline void add(int u,int v)

19 {

20     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;

21 }

22 

23 inline void read()

24 {

25     scanf("%d",&n);

26     for(int i=1;i<=n;i++)

27     {

28         scanf("%d",&a[i]);

29         a[i]-=i;

30     }

31 }

32 

33 inline void step1()

34 {

35     n++;

36     a[n]=0x3f3f3f3f; a[0]=-a[n];

37     for(int i=0;i<=n;i++) c[i]=0x3f3f3f3f;

38     len=1; c[1]=a[1]; c[0]=-c[0];

39     dp[0]=0; dp[1]=1;

40     for(int i=2;i<=n;i++)

41     {

42         int x=upper_bound(c,c+1+len,a[i])-c;

43         len=max(len,x);

44         c[x]=min(c[x],a[i]);

45         dp[i]=x;

46     }

47     cout<<n-dp[n]<<endl;

48 }

49 

50 inline void step2()

51 {

52     memset(head,-1,sizeof head); cnt=0;

53     for(int i=n;i>=0;i--) add(dp[i],i),f[i]=INF;

54     f[0]=0;

55     for(int i=1,tmp;i<=n;i++)

56         for(int j=head[dp[i]-1];~j;j=next[j])

57         {

58             if(to[j]>i) break;

59             if(a[to[j]]>a[i]) continue;

60             for(int k=to[j];k<=i;k++) sum1[k]=abs(a[k]-a[to[j]]),sum2[k]=abs(a[k]-a[i]);

61             for(int k=to[j]+1;k<=i;k++) sum1[k]+=sum1[k-1],sum2[k]+=sum2[k-1];

62             for(int k=to[j];k<i;k++)

63                 f[i]=min(f[i],f[to[j]]+sum1[k]-sum1[to[j]]+sum2[i]-sum2[k]);

64         }

65     cout<<f[n]<<endl;

66 }

67 

68 inline void go()

69 {

70     step1();

71     step2();

72 }

73 

74 int main()

75 {

76     read(),go();

77     return 0;

78 }

 

 

你可能感兴趣的:(ZOJ)