zafu 1467 (DP)

        Key Number

时间限制 : 1000 ms    内存限制 : 32 MB

提交次数 : 70    通过次数 : 34

题目描述

    我们称在一个序列中,按顺序出现的递增元素(不必连续)所构造出的最长序列集合为该序列的最长递增子序列。
例如序列1 3 2 8 4 9,它含有一些递增子序列,如:1 3;1 2 8;1 2 4 9;1 3 8 9等。
其中,我们无法找到长度大于4的递增子序列,所以该序列的最长递增子序列长度为4。  对于一个整数序列,
我们称其中的元素为不可分割之元素,当且仅当我们将它移去后,该序列的最长递增子序列的长度将会减小。
在上一段的例子中,9就是一个不可分割元素,因为去掉了9之后的序列为1 3 2 8 4,其最长递增子序列长度为3。    
于是现在的问题是,给出一组整数序列,求当前序列中不可分割元素的数目。    

输入描述

    第一行是一个整数T(T<=100),表示测试组数。    对于每组数据,第一个整数n(n<=100000),表示序列的长度。    然后是n个不超过10000的整数。

输出描述

    输出一行,表示不可分割元素的数目。

样例输入

3
1 2 3
2 2 1
9 1093 1200 1321 1000 0 2 7 3 12

样例输出

3
0
3

作者

Zhuangli

来源

浙江农林大学第十届电脑节程序设计大赛正式赛

 

/*
	    lost神题;
	    dp[i]记录到i 出现的最长子序列的长度;
       	当	dp1[i]+dp2[n-i+1]==l+1 
	    说明当前i包括在最长子序列内
	    ;
注意 :  dp1[i]指到当前i位置时出现的最长子序列,如果dp1[i]出现多次的话,说明当前的dp1[i]是可以替代的,
	    所以, hash[dp1[i]]++ , 线扫hash出现过一次的说明是不可删的,
	
*/


#include <stdio.h>
#include <math.h>
#include <string.h>
int queue[100001];
int dp1[100001],dp2[100001];
int s1[100001],s2[100001];
int hash[100001];
int n;
int LIS(int dp[],int s[])
{//求单调递增子序列
	int lenth=1,left,right,mid;
	queue[1]=s[1];dp[1]=1;
	for(int i=2;i<=n;i++)
	{
		left=1;right=lenth;
		while(left<right)
		{
			mid=(left+right)>>1;
			if(queue[mid]<s[i])
				left=mid+1;
			else   
				right=mid;
		}
		if(queue[left]<s[i])
		{	
			lenth++;right=lenth;
			queue[lenth]=s[i];
			dp[i]=left+1;
		}
		else
		{
			dp[i]=left;
			queue[left]=s[i];
		}
	}
	return lenth;
}
//
int LDS(int dp[],int s[])
{//单调递减子序列
	int lenth=1,left,right,mid;
	queue[1]=s[1];dp[1]=1;
	for(int i=2;i<=n;i++)
	{
		left=1;right=lenth;
		while(left<right)
		{
			mid=(left+right) >>1;//!!!!
			if(queue[mid]>s[i])
				left=mid+1;
			else   
				right=mid;
		}
		if(queue[left]>s[i])
		{	
			lenth++;right=lenth;
			queue[lenth]=s[i];
			dp[i]=left+1;
		}
		else
		{
			dp[i]=left;
			queue[left]=s[i];
		}
	}
	return lenth;
}
int main()
{
	int lenth,left,num,right,i,j,l,T;

	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d",&s1[i]);
			s2[n+1-i]=s1[i];
		}
		l=LIS(dp1,s1);
		LDS(dp2,s2);

		memset(hash,0,sizeof(hash));
		num=0;
		for(i=1;i<=n;i++)
		{
			if(dp1[i]+dp2[n-i+1]==l+1)
				hash[dp1[i]]++;
		}
		for(i=1;i<=n;i++)	if(hash[i]==1) num++;
		printf("%d\n",num);
	}
	return 0;
}
posted @ 2010-12-04 19:30  kfinder  阅读(219)  评论(0编辑  收藏  举报