1. 程式人生 > >Codeforces Gym 101623A - 動態規劃

Codeforces Gym 101623A - 動態規劃

個數 最優解 print ref val 我們 oid end pair

題目傳送門

  傳送門

題目大意

  給定一個長度為$n$的序列,要求劃分成最少的段數,然後將這些段排序使得新序列單調不減。

  考慮將相鄰的相等的數縮成一個數。

  假設沒有分成了$n$段,考慮最少能夠減少多少劃分。

  我們將這個序列排序,對於權值相同的一段數可以任意交換它們,每兩個相鄰數在原序列的位置中如果是$i, i + 1$,那麽劃分的段數就可以減少1.

  每次轉移我們考慮添加值相同的一段。

  每次轉移能不能將減少的段數加一取決於當前考慮的數在前一段內有沒有出現以及有沒有作為最左端點。

  因此我們記錄一個決策與最優解不同的次優解就能轉移了。

Code

  1 /**
  2  * Codeforces
  3  * Gym#101623A
  4  * Accepted
  5  * Time: 171ms
  6  * Memory: 18300k
  7  */
  8 #include <algorithm>
  9 #include <iostream>
 10 #include <cassert>
 11 #include <cstdlib>
 12 #include <cstdio>
 13 using namespace std;
 14 typedef bool
boolean; 15 16 #define pii pair<int, int> 17 #define fi first 18 #define sc second 19 20 ostream& operator << (ostream& out, pii x) { 21 out << "(" << x.fi << ", " << x.sc << ")"; 22 return out; 23 } 24 25 template <typename T> 26
void pfill(T* pst, const T* ped, T val) { 27 for ( ; pst != ped; *(pst++) = val); 28 } 29 30 template <typename T> 31 void pcopy(T* pst, const T* ped, T *pval) { 32 for ( ; pst != ped; *(pst++) = *(pval++)); 33 } 34 35 int n; 36 int *ar; 37 pii *ps; 38 39 inline void init() { 40 scanf("%d", &n); 41 ar = new int[(n + 1)]; 42 for (int i = 1; i <= n; i++) 43 scanf("%d", ar + i); 44 } 45 46 int *ss, *st; 47 boolean *exi; 48 inline void solve() { 49 ps = new pii[(n + 1)]; 50 ss = new int[(n + 1)]; 51 st = new int[(n + 1)]; 52 exi = new boolean[(n + 1)]; 53 pfill(exi, exi + n + 1, false); 54 int m = 0, diff = 0; 55 for (int i = 1; i <= n; i++) 56 if (i == 1 || ar[i] != ar[i - 1]) 57 ps[++m] = pii(ar[i], ++diff); 58 sort(ps + 1, ps + (n = m) + 1); 59 // for (int i = 1; i <= m; i++) 60 // cerr << ps[i] << endl; 61 ss[1] = 1; 62 for (int i = 2; i <= n; i++) 63 ss[i] = ((ps[i - 1].first == ps[i].first) ? (ss[i - 1]) : (i)); 64 st[n] = n; 65 for (int i = n - 1; i; i--) 66 st[i] = ((ps[i + 1].first == ps[i].first) ? (st[i + 1]) : (i)); 67 68 ss[0] = st[0] = 0; 69 pii f(0, -1), g(-14285700, -1), cf(-1, -1), cg(-1, -1); 70 for (int i = 1; i <= n; i++) { 71 if (ss[i] != i) 72 continue; 73 for (int j = max(ss[i - 1], 1); j <= st[i - 1]; j++) 74 exi[ps[j].second] = true; 75 for (int j = ss[i], x, uval; j <= st[i]; j++) { 76 x = ps[j].second; 77 if (exi[x - 1]) { 78 if (x - 1 == f.second && st[i - 1] > ss[i - 1]) 79 assert(x - 1 != g.second), uval = g.first + 1; 80 else 81 uval = f.first + 1; 82 uval = max(uval, f.first); 83 } else 84 uval = f.first; 85 if (uval > cf.first) 86 cg = cf, cf = pii(uval, x); 87 else if (x != cg.second && uval > cg.first) 88 cg = pii(uval, x); 89 } 90 for (int j = max(ss[i - 1], 1); j <= st[i - 1]; j++) 91 exi[ps[j].second] = false; 92 swap(cf, f); 93 swap(cg, g); 94 cf = pii(-14285700, -1), cg = pii(-14285700, -1); 95 // cerr << f << " " << g << endl; 96 } 97 printf("%d\n", n - f.first - 1); 98 } 99 100 int main() { 101 init(); 102 solve(); 103 return 0; 104 }

Codeforces Gym 101623A - 動態規劃