HDU 5256 序列變換(最長上升子序列)
Problem Description
我們有一個數列A1,A2…An,你現在要求修改數量最少的元素,使得這個數列嚴格遞增。其中無論是修改前還是修改後,每個元素都必須是整數。
請輸出最少需要修改多少個元素。
Input
第一行輸入一個T(1≤T≤10),表示有多少組資料
每一組資料:
第一行輸入一個N(1≤N≤105),表示數列的長度
第二行輸入N個數A1,A2,…,An。
每一個數列中的元素都是正整數而且不超過106。
Output
對於每組資料,先輸出一行
Case #i:
然後輸出最少需要修改多少個元素。
Sample Input
2
2
1 10
3
2 5 4
Sample Output
Case #1:
0
Case #2:
1
這算是一種比較簡單的模板變換題。
最長上升子序列,其中的元素位置可以不連在一起,而這道題,要求改變的最小的數字,等同於求出其最長的上升子序列,然而有限制。一開始我看了很多題解,上面都有說有限制,然而我還一臉懵逼,啥限制?
一般來說,上升的子序列符合一個公式:a[i]-a[j]>=i-j,其中,i 比 j 大。而這個公式變換一下就成了a[i]-i>=a[j]-j;既然你要在原陣列中改變數值,那麼改好之後的數值肯定比左邊的大,右邊的小,換句話說,你中間的位置是有了,值呢?比如這樣一個序列:3 5 4,a[1]-1=2,a[3]-3=1,前者並不大於後者,換句話說,中間無論怎麼改,都不可能符合條件,只可能是隻保留一個,改變兩個。
所以這道題可以這麼想,我要求的,既是最長上升子序列,又是其中的差值有足夠多的地方給我放改變過後的值,這樣子的子序列符合的條件就是上面那個公式了。
所以在一開始輸入的時候就對元素進行預處理。每個輸入的元素都減去他的位置。如此一來,後面就可以直接求最長上升子序列了。
而求最長上升子序列的方法,就是拿一個數組來存子序列,還要有一個變數來儲存最長的上升子序列的長度。而這個陣列初始化的時候是初始化成一個最大的數字的。
比如,我們用a[maxn]陣列來存子序列。a[1]表示長度為1的子序列的最大值中的最小值。比如長度為一的子序列有 1、2、3,那麼a[1]=1,為什麼要等於1呢?都是長度相同的子序列,與其保留大的,不如保留小的,這樣的話,這個序列和後面的值才更有可能會連起來,使得子序列的長度最長。而我們也不用每次都要從頭到尾的掃一遍得到那個最小值,只需要邊掃原陣列,邊處理就行,因為你的序列元素越前,能夠形成的子序列越長。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#define maxn 100010
#define maxm 10000010
using namespace std;
int T,n,k,len,ans,cnt;
int num[maxn];
int q[maxn];
int main()
{
scanf("%d",&T);
int cas=0;
while(T--)
{
scanf("%d",&n);
memset(q,sizeof(q),0);
for(int i=0;i<n;i++)
{
scanf("%d",&num[i]);
num[i]-=i;
}
for(int i=0;i<=n;i++) q[i]=maxm;
len=0;
cnt=0;
k=0;
for(int i=0;i<n;i++)
{
k=upper_bound(q,q+len,num[i])-q; //返回陣列中第一個比num[i]大的數字的位置。
if(q[k]==maxm) len++;
q[k]=num[i];
cnt=cnt>k?cnt:k;
}
cnt++;
ans=n-cnt;
printf("Case #%d:\n%d\n",++cas,ans);
}
return 0;
}
相關推薦
HDU 5256 序列變換(最長上升子序列)
Problem Description 我們有一個數列A1,A2…An,你現在要求修改數量最少的元素,使得這個數列嚴格遞增。其中無論是修改前還是修改後,每個元素都必須是整數。 請輸出最少需要修改多少個元素。 Input 第一行輸入一個T(1≤T≤10),
HDU 1069 Monkey and Banana 最長上升子序列進階(動態規劃)
HDU 1069(動態規劃) Monkey and Banana Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Description A group
每日三題-Day3-C(HDU 1257 最少攔截系統 最長上升子序列O(nlogn) )
原題地址 最少攔截系統 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 40250 Accepted Submi
POJ 1836 Alignment(DP max(最長上升子序列 + 最長下降子序列))
mission weight ring limit problem stream [0 sin ++ Alignment Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14486
HDU1257 最少攔截系統 —— 貪心 or LIS(最長上升子序列)
ret pre key ear out hide 裏來 程序 http 題目鏈接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1257 最少攔截系統 Time Limit: 2000/1000 MS (Java/Oth
HDU-1950 Bridging signals【最長上升子序列+二分+STL】
題目傳送門 題目:一個晶片左右各有n個結點,p[i]表示左邊第i個點與右邊第p[i]個點相連。求能取到的互不交叉的點的個數。 題解:本質就是求最長上升子序列,二分做法。對於一個上升子序列,顯然其結尾元素越小,越有利於在後面接其他的元素,也就越可能變得更長。 最長上升子序列詳解 A
CSU 1225: ACM小組的佇列(最長上升子序列的個數)
題目:DescriptionACM小組每次出去活動都要排隊,但是大家總是不想按照任何規則來排好這個隊伍(大概是因為每個人都比較有個性,例如Gestapolur),所以每次隊 伍都是亂的,不過Samsar
1836 Alignment (最長上升子序列 O(nlogn))
解題思路:是POJ2533的擴充套件題。 題意不難,令到原佇列的最少士兵出列後,使得新佇列任意一個士兵都能看到左邊或者右邊的無窮遠處。就是使新佇列呈三角形分佈就對了。 但這裡有一個陷阱,看了一些別人的解題報告說“任一士兵旁邊不能存在等高的士兵”,然後又舉了一個例
LIS(最長上升子序列)問題的三種求解方法以及一些例題
摘要 本篇部落格介紹了求LIS的三種方法,分別是O(n^2)的DP,O(nlogn)的二分+貪心法,以及O(nlogn)的樹狀陣列優化的DP,後面給出了5道LIS的例題。 LIS的定義 一個數的序列bi,當b1 < b2 < … <
uva 10635(最長上升子序列)
正是太蠢了,我做這道題居然做了幾天 一道經典的LCS,但也可以轉化成LIS 將A中的資料重新編排成{1,2,3,....},然後將B中的元素與A一一對應,如果B中的元素在A中沒有出現,就直接刪除。
【dp優化】LIS(最長上升子序列)長度的nlogn演算法
這道題第一反應就想到了 [CEOI96]渡輪問題 就是一個非常裸的求最長上升子序列的長度,還不要方案,非常的水。然而,常規的dp複雜度是 O(n^2) ,這道題會愉快地TLE,所以要進行nlogn級別的優化。 //O(n^2) TLE #include
HDU 1159 Common Subsequence(最長公共子序列)
大概題意:給出兩個字串s1,s2,求他們的最長公共子序列長度... 大概算是模板題? #include<cstdio> #include<cstring> #include<algorithm> #include<iostream&
HDU - 5532(Almost Sorted Array)最長上升子序列
題意: 給出一個長度為n的數列,問刪除一個數後,剩下的數列能否成為一個非遞增或非遞減數列,可以輸出“YES”,否則輸出“NO”。 題解: 使用兩次最長上升子序列(LIS)。(抄了抄板子) 第一次,求非遞減序列的最大長度,不用做任何處理。 第二次,
【HDU - 1025】Constructing Roads In JGShining's Kingdom(dp最長上升子序列模型 + 二分優化)
題幹: Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768
HDU-1905-Bridging signals(二分求最長上升子序列)
Bridging signals Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1167 Ac
hdu 1087 Super Jumping! Jumping! Jumping!(dp 最長上升子序列和)
Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. Maybe you are a good boy, and know little about this game,
最長上升子序列LIS(雲筆記圖片版)
ima 筆記 img 最長上升子序列 lis 技術 logs ges mage 最長上升子序列LIS(雲筆記圖片版)
O(N^2)最長上升子序列
turn ++ blog names i++ 最長上升子序列 連續 ios pan //最長上升子序列o(N^2)可以不連續的子序列, //狀態為maxlen[i]表示以a[i]為終點最大上升子序列長度 #include<iostream> #includ
HDU 1513 Palindrome:LCS(最長公共子序列)or 記憶化搜索
ble urn size rom str 個數 blog using reverse 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 題意: 給你一個字符串s,你可以在s中的任意位置添加任意字符,問你將s變成一個回
用樹狀數組寫的最長上升子序列(友好城市),nlogn。
log stream blog sum spa 最長上升子序列 () += def #include<iostream> #include<algorithm> #define maxn 100000 #define lb(x) x&-x