P1410 子序列
题目描述
给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列,
输入输出格式
输入格式:
若干行,每行表示一组数据。对于每组数据,首先输入一个整数N,表示序列的长度。之后N个整数表示这个序列。
输出格式:
同输入行数。对于每组数据,如果存在一种划分,则输出“Yes!”,否则输出“No!“。
输入输出样例
说明
【数据范围】
共三组数据,每组数据行数<=50,0 <= 输入的所有数 <= 10^9
第一组(30%):N <= 20
第二组(30%):N <= 100
第三组(40%):N <= 2000
//。。这道题。。。。我竟然不会做 //如果一个序列中的不升子序列长度>2了,那么这个序列一定就不能被分成2个lis了 //一定是>2个lis //emmmm ----> 最长不升子序列长度就是最大最长上升子序列的个数。 <---- //所以,如果一个序列能被分成两个长度相等的lis,那么最长不升子序列长度一定<=2 //如果==2的话,正好可以分成两个,否则原序列是个完全单调上升序列,把它怎么拆都能拆成两个长度相等的lis #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; const int N=2005; int n; int a[N]; int dp[N]; int lis[N],len; int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;++i) scanf("%d",a+i); lis[len=1]=a[1]; bool flag=0; for(int i=2;i<=n;++i) { if(a[i]>lis[len]) { int pos=lower_bound(lis+1,lis+len+1,a[i],greater<int>() )-lis; //lower_bound()真好用啊 if(pos==len+1) lis[1]=a[i]; //cout<<pos<<" "; else lis[pos]=a[i]; } else lis[++len]=a[i]; if(len>2) { flag=1; break; } } if(flag) puts("No!"); else puts("Yes!"); } return 0; }