最长上升子序列O(nlogn) 要强的T^T(2358)

题目来源:http://120.78.128.11/Problem.jsp?pid=2358

要强的T^T

TimeLimit:1000MS  MemoryLimit:65536K

64-bit integer IO format:%lld

Problem Description

T^T看到Home_W出了一道这么简短的数学题,觉得自己肯定也能出一道。于是便有了这题:

给定n个数,只包含1和2,问最少修改几个数,能使得n个数有序(单调不减)

Input

第一行包含一个数n,表示有n个数,接下来的n行是n个数。(1<=n<=30000)

Output

输出一行,包含最少修改次数

SampleInput

7

2 1 1 1 2 2 1

SampleOutput

2

思路:很明显的最长不下降子序列,但是这题要用到最长上升子序列的O(nlogn)优化方法,该优化方法是用一个数组保存长度为i的最长上升子序列的最小元素,比如对 a[N]={1, 2, 3, 0, 1}进行一边更新len_min数组,i=0, len_min[1]=1; i=1, len_min[2]=2; i=2, len_min[3]=3; i=3, len_min[1]=0,  len_min[2]=1。也就是说len_min保存的是到目前循环到的位置为止所有长度为i的子序列里第i位的最小值,就像len_min[1]在i=0(a[0]=1)时为1,但是到了i=3(a[3]=0)时就变成了0,因为长度为1的子序列目前最小的结尾数字已经变成了0。那么这个数组就可以用来二分查找一个数之前最长的子序列。设上界是目前为止的最长上升子序列长度,下界是1如果中间位置保存的值小于目前这个数,那么我们就可以认为这个数前面的最长上升子序列至少不小于那个中间位置的值。

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int N=30300;
 4 int Max(int a, int b) { return a>b?a:b; }
 5 int Min(int a, int b) { return a<b?a:b; }
 6 int a[N], dp[N], lmin[N], cmp;
 7 int main( ){
 8     int n, ans=1;
 9     memset(lmin, 0x3f, sizeof(lmin));
10     cmp=lmin[0];
11     scanf("%d", &n);
12     for(int i=0; i<n; i++)
13         scanf("%d", a+i), dp[i]=1;
14     lmin[1]=a[0];
15     for(int i=1; i<n; ++i){
16         int l=0, r=ans+1;
17         while(l+1<r){
18             int mid=(l+r)/2;
19             if(lmin[mid]>a[i]) r=mid;
20             else l=mid;
21         }
22         if(lmin[l]<=a[i]){
23             lmin[l+1]=Min(lmin[l+1], a[i]);
24             ans=Max(ans, l+1);
25         }
26         if(!l){
27             lmin[1]=Min(lmin[1], a[i]);
28         }
29     }
30     printf("%d\n", n-ans);
31     return 0;
32 }

拙略的代码

原文地址:https://www.cnblogs.com/DCD112358/p/8998046.html

时间: 2024-10-10 14:36:47

最长上升子序列O(nlogn) 要强的T^T(2358)的相关文章

最长递减子序列(nlogn)(个人模版)

最长递减子序列(nlogn): 1 int find(int n,int key) 2 { 3 int left=0; 4 int right=n; 5 while(left<=right) 6 { 7 int mid=(left+right)/2; 8 if(res[mid]>key) 9 { 10 left=mid+1; 11 } 12 else 13 { 14 right=mid-1; 15 } 16 } 17 return left; 18 } 19 20 int Lis(int a[

最长递增子序列 O(NlogN)算法

https://www.felix021.com/blog/read.php?entryid=1587&page=3&part=1 感谢作者! 标题:最长递增子序列 O(NlogN)算法 出处:Blog of Felix021 时间:Wed, 13 May 2009 04:15:10 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1587  内容: 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久

最长上升子序列 O(nlogn)解法 (转)

转自 http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更

(转载)最长递增子序列 O(NlogN)算法

原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素.注意d中元素是单调递增的,下面要用到这个性质.首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],

hdu 5773 最长递增子序列 (nlogn)+贪心

The All-purpose Zero Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 947    Accepted Submission(s): 453 Problem Description ?? gets an sequence S with n intergers(0 < n <= 100000,0<= S[i] &l

P3402 最长公共子序列(nlogn)

P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: 给定两个长度分别为n和m的序列,序列中的每个元素都是正整数.保证每个序列中的各个元素互不相同.求这两个序列的最长公共子序列的长度. DJL最讨厌重复劳动,所以不想做那些做过的题.于是他找你来帮他做作业. 输入输出格式 输入格式: 第一行两个整数n和m,表示两个数列的

最长上升子序列O(nlogn)算法详解

最长上升子序列 时间限制: 10 Sec   内存限制:128 MB 题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子序列长度是多少? 输入 第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N) 输出 1行,表示最长上升子序列的长度是多少. 样例输入 3 0 0 2 样例输出 2 提示 100%的数据 n&l

最长上升子序列 LIS nlogn

给出一个 1 - n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的n个整数组成的序列. Output 最长上升子序列的长度 题解 这里给出两种方法,先说经典版本的,设dp[i]表示以以 a[i]为结尾的LST的长度,n方的暴力很好想,显然我们在i之间找到一个最大的LST,且要保证a[j]<a[i],那么显然dp[i]=max(dp[i],dp[j]+1),那么这个dp显然就是在i之前找到一个以小于a[i]结尾元

51nod 1134 最长递增子序列 (O(nlogn)算法)

1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输