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", n - f.first - 1);
 98 }
 99
100 int main() {
101     init();
102     solve();
103     return 0;
104 }

原文地址:https://www.cnblogs.com/yyf0309/p/9846698.html

时间: 2024-12-19 05:18:53

Codeforces Gym 101623A - 动态规划的相关文章

Codeforces gym Hello 2015 Div1 B and Div2 D

Codeforces gym 100571 problem D Problem 给一个有向图G<V,E>和源点S,边的属性有长度L和颜色C,即E=<L,C>.进行Q次询问,每次给定一个点X,输出S到X的最短路的长度(不存在则输出 -1).但要求S到X的路径中相邻两条边颜色不一样. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 |V|, |E|: [1, 10^5] X, S: [1, |V| ] L: [1, 10^9] |C|

Codeforces gym Hello 2015 Div1 E

Codeforces gym 100570 problem E (一种处理动态最长回文子串问题的方法) Problem 给一个长度为N的字符串S,字符集是'a'-'z'.进行Q次操作,操作分三种.一,修改位置X的字符为C:二,查询以P位置为中心的最长回文子串的长度,并输出:三,查询以P与P+1的中间位置为中心的最长回文子串的长度,并输出. More 第二种操作子串长度为奇数,一定存在:第三种操作子串长度为偶数,若不存在,输出 -1. Limits Time Limit(ms): 4000(1s足

Codeforces gym Hello 2015 Div1 C and Div2 E

Codeforces gym 100570 problem C Codeforces gym 100571 problem E Problem 给一个N行M列的矩阵Ma,进行Q次(Q<=10)查询,每次给定一个K,问有多少子矩阵,满足最大值max - 最小值min <=K. Limits Time Limit(ms): 8000 Memory Limit(MB): 512 N, M: [1, 400] Q: [1, 10] Ma(i, j), K: [1, 10^9] Solution (Th

【模拟】ECNA 2015 I What&#39;s on the Grille? (Codeforces GYM 100825)

题目链接: http://codeforces.com/gym/100825 题目大意: 栅栏密码.给定N(N<=10),密钥为一个N*N的矩阵,'.'代表空格可以看到,'X'代表被遮挡,还有密文字符串S,长度为N*N 每次将这个矩阵顺时针旋转90°,把矩阵中空格对应的位置按照从上到下从左到右的顺序依次填充上密文字符,求最终这个密文字符能否填满N*N的矩阵,能按顺序输出得到的答案,不能输出"invalid grille" 题目思路: [模拟] 直接模拟即可.旋转的坐标公式很好推.

Codeforces gym Hello 2015 Div2 B

Codeforces gym 100571 problem B Problem 设函数F(x),F(1)与F(2)已知,且当 i>=3,F(i)=a*F(i-2)+b*F(i-1).再给一个长度为N的数列A,进行Q次如下操作:每次给一个区间[L, R],对于每个k(L=<k<=R),将A[k]=A[k]+F[k-L+1].最后输出数列A(mod 10^9+7). Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N, Q: [1, 10^

Codeforces Gym - 101147J Whistle&#39;s New Car

Discription Statements Whistle has bought a new car, which has an infinite fuel tank capacity. He discovered an irregular country since it has n cities and there are exactly n?-?1roads between them, of course, all cities are connected. He is so much

Codeforces Gym 101174 A Within Arm&#39;s Reach 贪心 手臂

#include<iostream> #include<stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> using namespace std; #define LL long long const int maxn=25; double a[maxn],l[maxn],r[maxn]; double ex,ey

Codeforces Gym 100269 Dwarf Tower (最短路)

题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game named "Dwarf Tower". In this game there are n different items,which you can put on your dwarf character. Items are numbered from 1 to n. Vasya want

CodeForces Gym 101063C 二进制压缩

http://codeforces.com/gym/101063/problem/C 给n个人,m样物品,每个人可以从物品中选择几样.两人选择物品的交集元素个数比上并集元素个数如果大于某个比例即可将两人配对.求配对数. n的范围是1e5,直接比较所有人的选择会TLE,应该将所有选择物品的情况用二进制压缩,m最大是10,情况数目小于2048,可以接受.注意配对总数范围应为long long. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> i