Codeforces Gym 101623A - 动态规划
Posted yyf0309
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Gym 101623A - 动态规划相关的知识,希望对你有一定的参考价值。
考虑将相邻的相等的数缩成一个数。
假设没有分成了$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 - f.first - 1); 98 } 99 100 int main() { 101 init(); 102 solve(); 103 return 0; 104 }
以上是关于Codeforces Gym 101623A - 动态规划的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces-gym-101020 problem C. Rectangles