1. 程式人生 > >HDU 5256 序列變換(最長上升子序列)

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-CHDU 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 AlignmentDP 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 - 5532Almost Sorted Array上升序列

題意: 給出一個長度為n的數列,問刪除一個數後,剩下的數列能否成為一個非遞增或非遞減數列,可以輸出“YES”,否則輸出“NO”。 題解: 使用兩次最長上升子序列(LIS)。(抄了抄板子) 第一次,求非遞減序列的最大長度,不用做任何處理。 第二次,

HDU - 1025】Constructing Roads In JGShining's Kingdomdp上升序列模型 + 二分優化

題幹: 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(雲筆記圖片版)

ON^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