Codeforces Gym 101623A - 动态规划

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Gym 101623A - 动态规划相关的知识,希望对你有一定的参考价值。

题目传送门

  传送门

题目大意

  给定一个长度为$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 - f.first - 1);
 98 }
 99 
100 int main() {
101     init();
102     solve();
103     return 0;
104 }

以上是关于Codeforces Gym 101623A - 动态规划的主要内容,如果未能解决你的问题,请参考以下文章

codeforces Gym 101063 C

codeforces Gym 100735 DEGHI

CodeForces Gym-101350M

Codeforces-gym-101020 problem C. Rectangles

2021-5-11 CSUST 周练 Codeforces Gym #102894

2021-5-11 CSUST 周练 Codeforces Gym #102894