POJ 3670

是考察LIS和LDS问题的nlogn解法,题意是找到牛队列中不符合非升(降)序趋势的编号个数,FJ给改过来,分别比较以非升序的规则和非降序的规则找,看哪个改动的最少,数据量大,nlogn。介绍一下这个算法的实现过程:模拟一个队列,初始空。然后读入牛的编号,第一个数据入列,然后再读入的时候开始比较:读入一个编号P,则跟队列头的元素比较,若大于头元素,则入列;否则二分遍历队列中的元素,找到第一个大于(从左至右)P的元素,替换之。读入复杂度是n,二分logn,总的就是nlogn。结果

就是队列的规模。然后是3671,题目都一样,只需看输出就知道是一个纯LIS,不需考虑LDS了,将3670的代码相应部分注释掉一SuBmit就刻不容缓的呕了。

#include<iostream> #include<algorithm> using namespace std; const int sup=30005; int LDS[sup];//不升 int LIS[sup];//不降 int dp[sup]; int n; int bsearch(int beg,int end,int p) { int mid; while(beg<=end)//二分很掣肘,试了好几次 { mid=(beg&end)+((beg^end)>>1); if(dp[mid]<=p) beg=mid+1; else if(dp[mid]>p) end=mid-1; } return beg; } int lis() { int i; int top=-1; for(i=0;i<n;++i) { if(dp[top==-1?0:top]<=LIS[i]) dp[++top]=LIS[i]; else if(dp[top==-1?0:top]>LIS[i]) dp[bsearch(0,top,LIS[i])]=LIS[i]; } return n-top-1; } int lds() { int i,top=-1; for(i=0;i<n;++i) { if(dp[top==-1?0:top]<=LDS[i]) dp[++top]=LDS[i]; else if(dp[top==-1?0:top]>LDS[i]) dp[bsearch(0,top,LDS[i])]=LDS[i];//由于是拷贝lis的代码,导致其中的一个LIS米有改过来,WAWAWA } return n-top-1; } int main() { int i; scanf("%d",&n); for(i=0;i<n;++i) { scanf("%d",&LIS[i]); LDS[n-i-1]=LIS[i]; } int ans=lis(); fill(dp,dp+sup,0); int t=lds(); ans=ans<t?ans:t; if(ans!=-1) printf("%d/n",ans); else printf("0/n"); return 0; }

你可能感兴趣的:(POJ 3670)