1. 程式人生 > >NJUST1925 sequence(貪心+二分)

NJUST1925 sequence(貪心+二分)

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;
}