最长上升子序列(LIS)算法
sicily 1060. Bridging Signals
最长严格上升子序列
#include<iostream> //最长严格上升子序列(LIS)算法,时间复杂度为O(nlogn)
using namespace std;
int seq[40010];
int main()
{
int cases,n,p;
cin>>cases;
while(cases--)
{
cin>>n>>p;
int rear=-1;
seq[++rear]=p;
while(--n)
{
cin>>p;
if(p>seq[rear]) //当p==seq[tail],不能压入最长严格上升子序列中
seq[++rear]=p;
else
{
int s=0,t=rear,mid; //在最长严格上升子序列中找到第一个大于p的数,并用p替换之。但如果有相同的元素已经在子序列出现,比如子序列是 3 4 , 要插入的值 p=3, 则子序列仍旧是 3 4 ,即插入的位置是相同的那个元素出现的位置(也就是不做任何改变)
while(s<t)
{
mid=(s+t)/2;
if(seq[mid]<p)
s=mid+1;
else //当seq[mid]==p时, t=mid, 因为若有相同元素出现,p要替换的并不是比p大的那个数,而是相同的那个数(即不做改变)
t=mid;
}
seq[s]=p;
}
}
cout<<rear+1<<endl; //最长严格上升子序列的长度
}
return 0;
}
poj 1887 Testing the CATCHER
最长不下降子序列
#include<iostream> //最长不下降子序列
using namespace std;
int num[10000],seq[10000];
int main()
{
int cases=1,p;
while(scanf("%d",&p),p!=-1)
{
int r=-1;
num[++r]=p;
while(scanf("%d",&p),p!=-1)
num[++r]=p;
for(int i=0;i<=r/2;++i)
swap(num[i],num[r-i]);
seq[0]=num[0];
int tail=0;
for(int i=1;i<=r;++i)
{
int p=num[i];
if(p>=seq[tail]) //当p==seq[tail],可以压入最长不下降子序列中
seq[++tail]=p;
else
{
int s=0,t=tail,mid; //在最长不下降子序列中找到第一个严格大于p的数,并用p替换之(即使有相同元素出现).比如子序列是 3 4 , 要插入的值 p=3, 则子序列更新为 3 3
while(s<t)
{
mid=(s+t)/2;
if(seq[mid]<=p) //当seq[mid]==p时, s=mid+1, 因为p要替换的是比p大的数,而不是相等的数
s=mid+1;
else
t=mid;
}
seq[s]=p;
}
}
printf("Test #%d:\n maximum possible interceptions: %d\n\n",cases++,tail+1);
}
return 0;
}
poj 1887 Testing the CATCHER
最长不上升子序列
#include<iostream> //最长不上升子序列
using namespace std;
int main()
{
int cases=1,seq[10000],p;
while(scanf("%d",&p),p!=-1)
{
int rear=-1;
seq[++rear]=p;
while(scanf("%d",&p),p!=-1)
{
if(p<=seq[rear])
seq[++rear]=p;
else
{
int s=0,t=rear,mid;
while(s<t)
{
mid=(s+t)/2;
if(seq[mid]>=p)
s=mid+1;
else
t=mid;
}
seq[s]=p;
}
}
printf("Test #%d:\n maximum possible interceptions: %d\n\n",cases++,rear+1);
}
return 0;
}