Description

为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐。每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批就餐的奶牛了。由于奶牛们不理解FJ的安排,晚饭前的排队成了一个大麻烦。 第i头奶牛有一张标明她用餐批次D_i(1 <= D_i <= 3)的卡片。虽然所有N(1 <= N <= 30,000)头奶牛排成了很整齐的队伍但谁都看得出来,卡片上的号码是完全杂乱无章的。 在若干次混乱的重新排队后,FJ找到了一种简单些的方法:奶牛们不动,他沿着队伍从头到尾走一遍把那些他认为排错队的奶牛卡片上的编号改掉,最终得到一个他想要的每个组中的奶牛都站在一起的队列,例如111222333或者333222111。哦,你也发现了,FJ不反对一条前后颠倒的队列,那样他可以让所有奶牛向后转,然后按正常顺序进入餐厅。 你也晓得,FJ是个很懒的人。他想知道,如果他想达到目的,那么他最少得改多少头奶牛卡片上的编号。所有奶牛在FJ改卡片编号的时候,都不会挪位置。

Input

第1行: 1个整数:N 第2..N+1行: 第i+1行是1个整数,为第i头奶牛的用餐批次D_i

Output

第1行: 输出1个整数,为FJ最少要改几头奶牛卡片上的编号,才能让编号变成他设想中的样子

Sample Input

5
1
3
2
1
1
输入说明:

队列中共有5头奶牛,第1头以及最后2头奶牛被设定为第一批用餐,第2头奶牛的预设是第三批用餐,第3头则为第二批用餐。

Sample Output

1

输出说明:

如果FJ想把当前队列改成一个不下降序列,他至少要改2头奶牛的编号,一种可行的方案是:把队伍中2头编号不是1的奶牛的编号都改成1。不过,如果FJ选择把第1头奶牛的编号改成3就能把奶牛们的队伍改造成一个合法的不上升序列了。

题解:

求出最长不下降子序列,正反各做一次,求最大的长度;

答案就为 n-maxl;

此题学习一下最长不下降子序列O(nlogn)的算法;

推导可见白书或是这里

我觉得可以通过理解代码理解原理:

	for(int i=1;i<=n;i++)
{
int k=lower_bound(g+1,g+n+1,a[i],cmp2)-g;
f[i]=k;
g[k]=a[i];
ans=max(ans,f[i]);
}

g可以理解为用来储存子序列,f为最长不下降子序列的长度;

lower_bound是在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置,具体的可以看这里

对于程序本身,我们可以这样理解:

找到第一个比a[i]大的元素的位置k,我们可以认为k就为当前找到的最长不下降子序列的长度;

用f记录下k;

把g[k]插在a[i]的前面(并不是替换),这样就可以前面的元素尽可能小,使下一步搜出来的k尽可能大了;

附上代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
bool cmp1(int a,int b)
{
return a<=b;
}
bool cmp2(int a,int b)
{
return a>=b;
}
int n,a[30003],f[30003],g[30003],ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
g[i]=INF;
for(int i=1;i<=n;i++)
{
int k=lower_bound(g+1,g+n+1,a[i],cmp1)-g;
f[i]=k;
g[k]=a[i];
ans=max(ans,f[i]);
}
for(int i=1;i<=n;i++)
g[i]=-INF;
for(int i=1;i<=n;i++)
{
int k=lower_bound(g+1,g+n+1,a[i],cmp2)-g;
f[i]=k;
g[k]=a[i];
ans=max(ans,f[i]);
}
printf("%d\n",n-ans);
return 0;
}

因为在某套模拟赛中又出现了这题原题,然后特别以为能特别轻松的拿满分来着,愉快的biabia之后,发现WA掉了!

说一下自己发现的细节:

我试着用了 挑战程序设计竞赛 那本提供的代码打了一遍,QAQ WA得特别的惨

注意的细节就是 k=lower_bound()-g;的值的问题,

感觉自己对于指针这种东西一直不是太懂,自己还是照着标准的打好了

读入的时候 从1开始读;

bool cmp(int a,int b){     return a<=b; }

for(int i=1;i<=n;i++) g[i] = INF;
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++){
int k=lower_bound(g+1,g+n+1,a[i],cmp)-g;
f[i]=k;
g[k]=a[i];
ans=max(ans,f[i]);
}

注意这里的cmp一定要定义,貌似没有定义一下会发生奇怪的事情;(不过有可能是因为我打开的方式不对)

然后就是一定不要作死按照书上的方式写!不就是多个f数组么- -

[Usaco2008 Feb]Eating Together麻烦的聚餐[最长不下降子序列]的更多相关文章

  1. Bzoj 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 二分

    1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1272  Solve ...

  2. BZOJ1609: [Usaco2008 Feb]Eating Together麻烦的聚餐

    1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 938  Solved ...

  3. BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐( LIS )

    求LIS , 然后用 n 减去即为answer ---------------------------------------------------------------------------- ...

  4. BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐

    1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Description 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按F ...

  5. 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐

    1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1010  Solv ...

  6. [Usaco2008 Feb]Eating Together麻烦的聚餐

    Description 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的 ...

  7. [BZOJ1609] [Usaco2008 Feb] Eating Together麻烦的聚餐 (dp)

    Description 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的 ...

  8. 【BZOJ】1609: [Usaco2008 Feb]Eating Together麻烦的聚餐(dp+被坑)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1609 首先我不得不说,我被这题坑了.题目前边没有说可以不需要3种牛都有啊!!!!!!!!然后我一直在 ...

  9. 【bzoj1609】[Usaco2008 Feb]Eating Together麻烦的聚餐 dp

    题目描述 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批 ...

随机推荐

  1. SD3.0四个协议解读

    前面的文章提到过SD卡主要分为两个操作模式,一是初始化和识别操作模式.还有一种就是这篇文章须要分析的传输数据模式啦. 传输数据模式: 传输数据模式主要有六种状态,各自是Stand-by状态.Trans ...

  2. ASP.NET 5简介

    ASP.NET 5简介 解读ASP.NET 5 & MVC6系列(1):ASP.NET 5简介 2015-05-13 09:14 by 汤姆大叔, 3379 阅读, 39 评论, 收藏, 编辑 ...

  3. oracle_根据ID(字符型)建立分区表

    方案思路:有一张暴增的数据表(10亿级别),以后需求需要提高单条查询性能, 这个表有个唯一ID, 假设是UUID,采用区分首字母的方法,不同字母的数据入到不同的物理文件中. 第一步: 查找数据库服务器 ...

  4. 传智播客.Net培训就业班入学测试题

    2.对学员的结业考试成绩评测,要求在控制台中提示用户输入学员考试成绩,写一个方法,根据用户输入的成绩,返回一个等级:90分以上A级.80~90分B级.70~80分C级.60~70分B级.60分以下C级 ...

  5. 数据库数据导出成XML文件

    在数据库中,怎样把库中的数据导出XML文件, sql语句如下: SELECT *  FROM 表名 FOR XML AUTO, ELEMENTS

  6. Self referencing loop detected with type

    json.net namespace EFDAL{    using System;    using System.Collections.Generic;    using Newtonsoft. ...

  7. WSockExpert[抓包工具]

    一.WSockExpert简单介绍          WSockExpert是一个抓包工具,它能够用来监视和截获指定进程网络数据的传输,对測试站点时非常实用.在黑客的手中,它经常被用来改动网络发送和接 ...

  8. 什么是EF, 和 Entity Framework Demo简单构建一个良好的发展环境

     Entity Framwork(实体框架.缩写EF)这是ORM(Object Relational Mapping.对象映射关系)一个解决方案. EF的表映射为实体.并封装了操作方法.方便开发者 ...

  9. Codeforces 484B Maximum Value(高效+二分)

    题目链接:Codeforces 484B Maximum Value 题目大意:给定一个序列,找到连个数ai和aj,ai%aj尽量大,而且ai≥aj 解题思路:类似于素数筛选法的方式,每次枚举aj,然 ...

  10. UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)

    在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位And ...