Problem Description
大家都知道小明最喜歡研究跟序列有關的問題了,可是也就因為這樣,小明幾乎已經玩遍各種序列問題了。可憐的小明苦苦地在各大網站上尋找著新的序列問題,可是找來找去都是自己早已研究過的序列。小明想既然找不到,那就自己來發明一個新的序列問題吧!小明想啊想,終於想出了一個新的序列問題,他欣喜若狂,因為是自己想出來的,於是將其新序列問題命名為“小明序列”。
提起小明序列,他給出的定義是這樣的:
①首先定義S為一個有序序列,S={ A1 , A2 , A3 , ... , An },n為元素個數 ;
②然後定義Sub為S中取出的一個子序列,Sub={ Ai1 , Ai2 , Ai3 , ... , Aim },m為元素個數 ;
③其中Sub滿足 Ai1 < Ai2 < Ai3 < ... < Aij-1 < Aij < Aij+1 < ... < Aim ;
④同時Sub滿足對於任意相連的兩個Aij-1與Aij都有 ij - ij-1 > d (1 < j <= m, d為給定的整數);
⑤顯然滿足這樣的Sub子序列會有許許多多,而在取出的這些子序列Sub中,元素個數最多的稱為“小明序列”(即m最大的一個Sub子序列)。
例如:序列S={2,1,3,4} ,其中d=1;
可得“小明序列”的m=2。即Sub={2,3}或者{2,4}或者{1,4}都是“小明序列”。
當小明發明了“小明序列”那一刻,情緒非常激動,以至於頭腦凌亂,於是他想請你來幫他算算在給定的S序列以及整數d的情況下,“小明序列”中的元素需要多少個呢?
Input
輸入數據多組,處理到文件結束;
輸入的第一行為兩個正整數 n 和 d;(1<=n<=10^5 , 0<=d<=10^5)
輸入的第二行為n個整數A1 , A2 , A3 , ... , An,表示S序列的n個元素。(0<=Ai<=10^5)
Output
請對每組數據輸出“小明序列”中的元素需要多少個,每組測試數據輸出一行。
Sample Input
2 0
1 2
5 1
3 4 5 1 2
5 2
3 4 5 1 2
Sample Output
2
2
1
題意:仍然是求LIS的長度,但是要求下標之間的差必須在題目要求范圍之內。
思路:要注意標記,詳細見代碼
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int ans,a[100005],dp[100005],c[100005],n,k; //a數組存放序列 //dp記錄在i點時最長的遞增子序列長度 //c數組為每次查找時候的標記,記錄路徑 int bin(int t) { int l = 1,r = n; while(l<=r) { int mid = (l+r)/2; if(t>c[mid]) l = mid+1; else r = mid-1; } return l; } int LIS() { int i,j; ans = 0; for(i = 1; i<=n; i++) { dp[i] = bin(a[i]); if(dp[i]>ans)//更新最長長度 ans = dp[i]; j = i-k;//因為需要相隔為K if(j>0 && c[dp[j]]>a[j])//查找標記 c[dp[j]] = a[j]; } return ans; } int main() { int t,i; while(~scanf("%d%d",&n,&k)) { for(i = 1; i<=n; i++) { scanf("%d",&a[i]); c[i] = 10000000; } printf("%d\n",LIS()); } return 0; }