USACO 4.3 Buy Low, Buy Lower (DP,高精度,(离散化))

2015-03-26 20:22:33

思路:这道题与POJ1952是一样的... 不过那题数据水,long long可水过。

  目前,对于这种求最长下降(/上升)子序列的长度以及种类的问题,我只能想到n^2的方法咯...

  考虑到长度最长5000,稍微构造下就能超long long,所以大数模板上好先。

  首先,if(v[j] > v[i]) dp[i] = max(dp[i],dp[j + 1]) (j < i) 从朴素的方程出发。

    因为要计数,要单独用大数开一个计数cnt数组。

  其次,这题求的是种类,要防止重复,所以对于相同的数字,我们计数时只能算位置最靠后的。位置靠后的数字已经包含前面相同数字的种类了。

    比如:7 6 5 3 5 4 6 ,当算到4时,往前遍历到两个5,如果都计算的话,会出现两次 7 6 5 这个序列,显然重复。

    关于这个问题的解决,用标记数组来标记当前已经出现过的数字。

    (1)可以从当前位置往前扫描,把相同的数字标记掉,比较暴力。我poj1952就是这样做的。(2)离散化掉后直接标记数值已经出现。

  最后,在统计答案时也要防止重复!同样需要开数组进行标记。

  1 /*
  2 ID:naturec1
  3 PROG: buylow
  4 LANG: C++
  5 */
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <cstdlib>
  9 #include <cmath>
 10 #include <vector>
 11 #include <map>
 12 #include <set>
 13 #include <stack>
 14 #include <queue>
 15 #include <string>
 16 #include <iostream>
 17 #include <algorithm>
 18 using namespace std;
 19 
 20 #define MEM(a,b) memset(a,b,sizeof(a))
 21 #define REP(i,n) for(int i=1;i<=(n);++i)
 22 #define REV(i,n) for(int i=(n);i>=1;--i)
 23 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 24 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
 25 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 26 #define MP(a,b) make_pair(a,b)
 27 
 28 typedef long long ll;
 29 typedef pair<int,int> pii;
 30 const int INF = (1 << 30) - 1;
 31 const int MAXN = 5010;
 32 const int maxn = 100;
 33 
 34 struct bign{
 35     vector<int> s;
 36     bign(){
 37         s.clear();
 38     }
 39     bign operator = (int val){
 40         s.clear();
 41         while(val){
 42             s.push_back(val % 10);
 43             val /= 10;
 44         }
 45         return *this;
 46     }
 47     bign operator = (bign B){
 48         s = B.s;
 49         return *this;
 50     }
 51     bign operator + (bign B){
 52         bign res;
 53         int c = 0,top = max(s.size(),B.s.size()),v1,v2;
 54         for(int i = 0; i < top; ++i){
 55             v1 = i < s.size() ? s[i] : 0;
 56             v2 = i < B.s.size() ? B.s[i] : 0;
 57             res.s.push_back((v1 + v2 + c) % 10);
 58             c = (v1 + v2 + c) / 10;
 59         }
 60         if(c) res.s.push_back(c);
 61         return res;
 62     }
 63     void print(){
 64         for(int i = s.size() - 1; i >= 0; --i)
 65             printf("%d",s[i]);
 66     }
 67 };
 68 
 69 int N;
 70 int v[MAXN],tv[MAXN];
 71 int dp[MAXN];
 72 int vis[MAXN];
 73 
 74 bign cnt[MAXN];
 75 
 76 int main(){
 77     freopen("buylow.in","r",stdin);
 78     freopen("buylow.out","w",stdout);
 79     scanf("%d",&N);
 80     REP(i,N) scanf("%d",v + i),tv[i] = v[i];
 81     sort(tv + 1,tv + N + 1);
 82     int sz = unique(tv + 1,tv + N + 1) - tv;
 83     REP(i,N) v[i] = lower_bound(tv + 1,tv + sz + 1,v[i]) - tv;
 84     int ans = 0;
 85     REP(i,N){
 86         MEM(vis,0);
 87         dp[i] = 1;
 88         cnt[i] = 1;
 89         vis[v[i]] = 1;
 90         for(int j = i - 1; j >= 1; --j) if(v[j] > v[i]){
 91             if(dp[j] + 1 > dp[i]){
 92                 dp[i] = dp[j] + 1;
 93                 cnt[i] = cnt[j];
 94             }
 95             else if(dp[j] + 1 == dp[i]){
 96                 if(!vis[v[j]]){
 97                     cnt[i] = cnt[i] + cnt[j];
 98                 }
 99             }
100             vis[v[j]] = 1;
101         }
102         if(dp[i] > ans) ans = dp[i];
103     }
104     printf("%d ",ans);
105     MEM(vis,0);
106     bign anscnt;
107     anscnt = 0;
108     for(int i = N; i >= 1; --i) if(!vis[v[i]] && dp[i] == ans){
109         vis[v[i]] = 1;
110         anscnt = anscnt + cnt[i];
111     }
112     anscnt.print();
113     puts("");
114     return 0;
115 }

 

posted @ 2015-03-26 20:53  Naturain  阅读(99)  评论(0编辑  收藏  举报