第一次写nlogn复杂度的LIS,纪念一下。
题目意思是说。有两条平行线,两条平行线都有n个城市,都是从左到右标记为1--n,一条线上是富有城市,一个是贫穷城市。输入n,接下来有n行,p,r表示穷城市p和富有城市r
之间能够建一条路(p的顺序是1--n,一个贫穷城市仅仅相应一个富有城市(弱爆的语文描写叙述能力T_T))。公路不能交叉。
问最多能够建多少条公路。
在别处看到的对nlogn解法的解释吧算是:
时间复杂度:(NlogN):
除了算法一的定义之外。添加一个数组b,b[i]用以表示长度为i最长子序列的最后一个数最小能够是多少。易证:i<j时。b[i]<b[j]。
在二分查找时,一直更新b[]内容。设此时b的总长度为k,
若1. arr[i] >= b[k], 则b[k+1] = arr[i];
若2. arr[i] < b[k], 则在b[1..k]中用二分搜索大于arr[i]的最小值,返回其位置pos。然后更新b[pos]=arr[i]。
code例如以下(自己手写了一个二分,又用了下STL里面upper_bound。都能够):
//#pragma comment(linker,"/STACK:102400000,102400000") #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> //#define local using namespace std; const int maxn=500010; int poor[maxn],ro[maxn]; int n; int Binary_search(int x,int k) { int low=1,high=k; while(low<=high) { int mid=(low+high)/2; if(ro[mid]<=x) low=mid+1; else high=mid-1; } return low; } int lis() { int k=1; ro[k]=poor[1]; for(int i=2;i<=n;i++) { if(poor[i]>=ro[k]) ro[++k]=poor[i]; else { //int pos=Binary_search(poor[i],k); int pos=upper_bound(ro+1,ro+k+1,poor[i])-(ro); ro[pos]=poor[i]; } } return k; } int main() { #ifdef local freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // local int cnt=0; while(~scanf("%d",&n)) { int x,y; for(int i=0;i<n;i++) { scanf("%d%d",&x,&y); poor[x]=y; } int ans=lis(); printf("Case %d:\n",++cnt); if(ans<=1) printf("My king, at most %d road can be built.\n\n",ans); else printf("My king, at most %d roads can be built.\n\n",ans); } return 0; }
hdu1025 Constructing Roads In JGShining's Kingdom (nlogn的LIS)
时间: 2024-10-23 04:52:57