NJUST1925 sequence(貪心+二分)
阿新 • • 發佈:2019-02-15
sequence
Time Limit: 1000MS
Memory Limit: 65536KB
Description
將一個給定的數列,拆分成K個不降序列,每個數出現且只出現一次,且在各序列中各個數相對於原數列的相對順序不變。如7 6 9 8 10可以拆成 7 9 10和6 8。求最小的K值。Input
第一行輸入一個整數T(1 <= T <= 100),表示接下來T組測試資料,每組兩行,第一行為n,代表數列長度(1<=n<=10000)接下來一行有n個數,空格分隔(每個數<=50000)。Output
對每組資料輸出一個最小的K值。Sample Input
2 5 7 6 9 8 10 5 5 4 3 2 1
Sample Output
2
5
分析:
用一個數組arrMax維護每個序列的最大值,當新輸入一個數val,然後在arrMax裡面找到一個最大的數x,使得x<=val,那麼將數組裡面的x更新為val,表示val加入到那個曾經以x為最大值的升序序列,此時序列的個數不變。
若序列中的每一個都比val大,那麼就必須重新建立一個序列了。
程式碼:
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; const LL INF = 1e9+7; const LL MINT = ~0u>>1; const int maxn = 12345; int arrMax[maxn],nArr; //維護每一個序列的最大值 void update(int val) { int down=0,mid,up=nArr; int index = nArr; while(down<=up) { mid=(down+up)>>1; if(arrMax[mid]<=val) { up=mid-1; if(index>mid) index=mid; } else down=mid+1; } arrMax[index]=val; } int main() { int nCase; scanf("%d",&nCase); while(nCase--) { int n,ans=0; nArr = 0; scanf("%d",&n); while(n--) { int val; scanf("%d",&val); if(0 == nArr || arrMax[nArr-1]>val) arrMax[nArr++]=val; else update(val); } printf("%d\n",nArr); } return 0; }