poj 3298 Antimonotonicity
#include<iostream> //DP, 与sicily 1685. Missile 类似,但数据规模较大,O(n^2)肯定会TLE
#include<stdio.h>
using namespace std;
int num[30010],ans[30010],odd,even; //ans[i]存放形成的序列上的第i个数,假若i表示偶数,则ans[i]<ans[i+1],所以第偶数上的值越小越好,而第奇数上的值越大越好
int main()
{
int t,n;
cin>>t;
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&num[i]); //num[]是原始数据
for(int i=1;i<=n;++i)
ans[i]=0;
ans[1]=num[1];
odd=1;even=0; //odd,even记录当前序列若是奇数个(偶数个)的最大长度
for(int i=2;i<=n;++i)
{
if(ans[1]<num[i])
ans[1]=num[i];
int j,k;
for(j=even;j>0;j-=2)
{
if(ans[j]>num[i])
{
ans[j]=num[i]; //偶数个上的值越小越好,如果执行了ans[j]=num[i];则不必要再往下查找了
break;
}
else if(ans[j+2]>0&&ans[j+2]<ans[j]) //如果偶数个上的值较大而长度却较小,那也不必要再往下查找了,因为这个总是最优解.下面类似.倘若没有这一句,就会超时
break;
}
for(j=even;j>0;j-=2)
{
if(ans[j]<num[i]&&(ans[j+1]<num[i]||ans[j+1]==0))
{
if(ans[j+1]==0) //num[i]是插到最尾部
odd+=2;
ans[j+1]=num[i]; //num[i]替换ans[j+1]的条件(j是偶数):(1)num[i]要大于ans[j],因为奇数位上的值要大于偶数位上的值;(2)如果ans[j+1]存在,num[i]要大于ans[j+1],因为奇数上的值越大越好
break;
}
else if(ans[j+2]>0&&ans[j+2]<ans[j])
break;
}
for(k=odd;k>0;k-=2)
{
if(ans[k]<num[i])
{
ans[k]=num[i];
break;
}
else if(ans[k+2]>0&&ans[k+2]>ans[k])
break;
}
for(k=odd;k>0;k-=2)
{
if(ans[k]>num[i]&&(ans[k+1]>num[i]||ans[k+1]==0))
{
if(ans[k+1]==0)
even+=2;
ans[k+1]=num[i];
break;
}
else if(ans[k+2]>0&&ans[k+2]>ans[k])
break;
}
}
printf("%d\n",max(odd,even));
}
return 0;
}