好 蛋疼 终于ac了~~
实际就是求从某个点开始,的最长不降子序列和最长不升子序列之和 减去两个中重复的数字~
#include <cstring>
#include <iostream>
#include <cstdio>
using namespace std;
const int inf=0x3f3f3f3f;
int num[100005];
int q1[100005];
int q2[100005];
int res[100005];
void Scan(int &num) //对G++使用
{
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-')
{
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
}
int Bsearch1(int l,int r,int x)
{
while(l<=r)
{
int mid=(l+r)>>1;
if(q1[mid]<=x)
l=mid+1;
else
r=mid-1;
}
return l;
}
int _Bsearch1(int l,int r,int x)
{
while(l<=r)
{
int mid=(l+r)>>1;
if(q1[mid]<x)
l=mid+1;
else
r=mid-1;
}
return r;
}
int Bsearch2(int l,int r,int x)
{
while(l<=r)
{
int mid=(l+r)>>1;
if(q2[mid]>=x)
l=mid+1;
else
r=mid-1;
}
return l;
}
int _Bsearch2(int l,int r,int x)
{
while(l<=r)
{
int mid=(l+r)>>1;
if(q2[mid]>x)
l=mid+1;
else
r=mid-1;
}
return r;
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
int n;
Scan(n);
int i;
for(i=1;i<=n;i++)
Scan(num[i]);
int k1=0,k2=0;
q1[k1]=-inf;
q2[k2]=inf;
int ans1,ans2;
for(i=n;i>=1;i--)
{
int l1=1,l2=1;
if(num[i]>=q1[k1])
{
q1[++k1]=num[i];
ans1=k1;
}
else
{
int pos=Bsearch1(1,k1,num[i]);
q1[pos]=num[i];
ans1=pos;
}
l1=ans1-_Bsearch1(1,k1,num[i]); //求出相同的个数
if(num[i]<=q2[k2])
{
q2[++k2]=num[i];
ans2=k2;
}
else
{
int pos=Bsearch2(1,k2,num[i]);
q2[pos]=num[i];
ans2=pos;
}
l2=ans2-_Bsearch2(1,k2,num[i]); //求出相同的个数
res[i]=ans1+ans2-min(l1,l2);
}
int mm=0;
for(i=1;i<=n;i++)
if(mm<res[i])
mm=res[i];
printf("%d\n",mm);
}
}