题目传送门

  传送门

题目大意

  给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减。

  考虑将相邻的相等的数缩成一个数。

  假设没有分成了$n$段,考虑最少能够减少多少划分。

  我们将这个序列排序,对于权值相同的一段数可以任意交换它们,每两个相邻数在原序列的位置中如果是$i, i + 1$,那么划分的段数就可以减少1.

  每次转移我们考虑添加值相同的一段。

  每次转移能不能将减少的段数加一取决于当前考虑的数在前一段内有没有出现以及有没有作为最左端点。

  因此我们记录一个决策与最优解不同的次优解就能转移了。

Code

 /**
* Codeforces
* Gym#101623A
* Accepted
* Time: 171ms
* Memory: 18300k
*/
#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <cstdio>
using namespace std;
typedef bool boolean; #define pii pair<int, int>
#define fi first
#define sc second ostream& operator << (ostream& out, pii x) {
out << "(" << x.fi << ", " << x.sc << ")";
return out;
} template <typename T>
void pfill(T* pst, const T* ped, T val) {
for ( ; pst != ped; *(pst++) = val);
} template <typename T>
void pcopy(T* pst, const T* ped, T *pval) {
for ( ; pst != ped; *(pst++) = *(pval++));
} int n;
int *ar;
pii *ps; inline void init() {
scanf("%d", &n);
ar = new int[(n + )];
for (int i = ; i <= n; i++)
scanf("%d", ar + i);
} int *ss, *st;
boolean *exi;
inline void solve() {
ps = new pii[(n + )];
ss = new int[(n + )];
st = new int[(n + )];
exi = new boolean[(n + )];
pfill(exi, exi + n + , false);
int m = , diff = ;
for (int i = ; i <= n; i++)
if (i == || ar[i] != ar[i - ])
ps[++m] = pii(ar[i], ++diff);
sort(ps + , ps + (n = m) + );
// for (int i = 1; i <= m; i++)
// cerr << ps[i] << endl;
ss[] = ;
for (int i = ; i <= n; i++)
ss[i] = ((ps[i - ].first == ps[i].first) ? (ss[i - ]) : (i));
st[n] = n;
for (int i = n - ; i; i--)
st[i] = ((ps[i + ].first == ps[i].first) ? (st[i + ]) : (i)); ss[] = st[] = ;
pii f(, -), g(-, -), cf(-, -), cg(-, -);
for (int i = ; i <= n; i++) {
if (ss[i] != i)
continue;
for (int j = max(ss[i - ], ); j <= st[i - ]; j++)
exi[ps[j].second] = true;
for (int j = ss[i], x, uval; j <= st[i]; j++) {
x = ps[j].second;
if (exi[x - ]) {
if (x - == f.second && st[i - ] > ss[i - ])
assert(x - != g.second), uval = g.first + ;
else
uval = f.first + ;
uval = max(uval, f.first);
} else
uval = f.first;
if (uval > cf.first)
cg = cf, cf = pii(uval, x);
else if (x != cg.second && uval > cg.first)
cg = pii(uval, x);
}
for (int j = max(ss[i - ], ); j <= st[i - ]; j++)
exi[ps[j].second] = false;
swap(cf, f);
swap(cg, g);
cf = pii(-, -), cg = pii(-, -);
// cerr << f << " " << g << endl;
}
printf("%d\n", n - f.first - );
} int main() {
init();
solve();
return ;
}

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

  1. Codeforces Gym 101252D&&floyd判圈算法学习笔记

    一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...

  2. Codeforces Gym 101190M Mole Tunnels - 费用流

    题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...

  3. 【Codeforces Gym 100725K】Key Insertion

    Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...

  4. Codeforces gym 101343 J.Husam and the Broken Present 2【状压dp】

     2017 JUST Programming Contest 2.0 题目链接:Codeforces gym 101343 J.Husam and the Broken Present 2 J. Hu ...

  5. codeforces gym 100553I

    codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...

  6. CodeForces Gym 100213F Counterfeit Money

    CodeForces Gym题目页面传送门 有\(1\)个\(n1\times m1\)的字符矩阵\(a\)和\(1\)个\(n2\times m2\)的字符矩阵\(b\),求\(a,b\)的最大公共 ...

  7. Codeforces GYM 100876 J - Buying roads 题解

    Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...

  8. codeforces Gym 100187J J. Deck Shuffling dfs

    J. Deck Shuffling Time Limit: 2   Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...

  9. Codeforces Gym 100187K K. Perpetuum Mobile 构造

    K. Perpetuum Mobile Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...

随机推荐

  1. LG3834 可持久化线段树1

    题意 给定\(N\)个整数构成的序列,将对于指定的闭区间查询其区间内的第\(K\)小值. $n \leq 2 \times 10^5 $ 思路 在\([l,r]\)区间内的数的个数,可以用\(sum[ ...

  2. HibernateValidators

    public final class HibernateValidators { private static final Validator VALIDATOR; private Hibernate ...

  3. [svc]tcp三次握手四次挥手&tcp的11种状态(半连接)&tcp的time-wait

    TCP的状态转化过程(11种状态)以及TIME_WAIT状态 高性能网络 | 你所不知道的TIME_WAIT和CLOSE_WAIT 我相信很多都遇到过这个问题.一旦有用户在喊:网络变慢了.第一件事情就 ...

  4. 【Linux】Mac Centos install VMware Tools

    can't use yum: vi /etc/sysconfig/network-scripts/ifcfg-enp4s0 yum -y install lshw pciutils gdisk sys ...

  5. 【Docker】-NO.132.Docker.1 -【Docker 修改容器端口】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  6. Js数组去重方法总结

    //方法一 var arr = [1,23,1,1,1,3,23,5,6,7,9,9,8,5]; function removeDuplicatedItem(arr) { for(var i = 0; ...

  7. UIElementImageShot

    MemoryStream memStream = new MemoryStream(); System.Windows.Media.Imaging.RenderTargetBitmap bmp = n ...

  8. html5 css练习 画廊 元素旋转

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  9. IT题库-134 | String、StringBuffer和StringBuilder的区别

    String是不可变的: StringBuffer是可变的,有默认长度的缓冲区,缓冲区一出时,则会自动增加: StringBuilder也是可变的,同上: StringBuffer是线程安全的(方法实 ...

  10. 微信网页授权获取用户openid及用户信息

    $code = $_GET["code"];//获取code $appid=“xxxx”;//公众号appid $APPSECRET="xxx";//公众号ap ...