Vijos P1369难解的问题

来源:互联网 发布:织物工艺设计软件 编辑:程序博客网 时间:2024/04/29 10:44

一开始以为只要一次LIS,在更新时候不动第K个元素所在的位置即可,发现这样只能过百分之80的数据。

看了下特解的说法,发现可以用2次LIS求,一次以K项为结尾,一次以K项为开始,分别求,然后把结果加起来即可。

注意的是二分的一些修改。


/*题意:求出的最长上升子序列必须含有第K项解法:分别求2次LIS(第一次:以第K项为结尾(一定要包含第K项)的最长LIS+                    第二次:以第K项为开始(一定要包含第K项)的最长LIS)注意的地方:要用长整型,二分查找的修改由temp>=dp[mid].num修改为temp>dp[mid].num因为例如数据 14 3  0 0 0 6 8 4 5 6 7 9 8 9 5 10 注意观察前三项在DP时的变化。*/#include<iostream>using namespace std;const int MAXN=300005;struct Node{long long int num;};Node dp[MAXN];int main(){int n,k,top=0,len=0;long long int temp;cin>>n>>k;dp[0].num=-1;for(int i=1;i<=k;i++)//第一次DP,以K为结尾。{cin>>temp;if(temp>dp[top].num){dp[++top].num=temp;if(i==k)//如果最后一项能够接在后面形成更长的LIS,则第一次DP的长度为top(即++后的top)。{len=top;}}else{int l=1,r=top,mid;while(l<=r){mid=(l+r)/2;if(temp>dp[mid].num){l=mid+1;}else{r=mid-1;}}dp[l].num=temp;if(i==k)//若不能接在当前top后面形成更长的LIS,则寻找第K项能接的最长的LIS的位置。{       //因为一定要包含第K项,则当前所接的位置就是第一次DP的最长LIS的长度。为l。len=l;}}}dp[1].num=temp;//重新初始化DP的开始,以第K项为开始。top=1;//重新初始化以第K项为开始的LIS,当前只有一项(第K个元素),即为1for(int i=k+1;i<=n;i++)//第二次DP,以K项为开始。{cin>>temp;if(temp>dp[top].num){dp[++top].num=temp;}else{int l=1,r=top,mid;while(l<=r){mid=(l+r)/2;if(temp>dp[mid].num){l=mid+1;}else{r=mid-1;}}if(l!=1){dp[l].num=temp;}}}len=len+top-1;//因为第K项重复计算了2遍。cout<<len<<endl;return 0;}


0 0