生活随笔
收集整理的這篇文章主要介紹了
POJ 1631 nlogn求LIS
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
方法一: 二分
我們可以知道 最長上升子序列的 最后一個數的值是隨序列的長度而遞增的 (呃呃呃 意會意會)
然后我們就可以二分找值了(并更新)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,cases,a[
100050],f[
100050],vis[
100050];
int search(
int x){
int l=
0,r=n,ans=
0;
while(l<=r){
int mid=(l+r)>>
1;
if(vis[mid]<=x)l=mid+
1,ans=mid;
else r=mid-
1;}
return ans;
}
int main()
{
scanf(
"%d",&cases);
while(cases--){
memset(f,
0,
sizeof(f));
memset(vis,
0x3f,
sizeof(vis)),vis[
0]=
0;
scanf(
"%d",&n);
for(
int i=
1;i<=n;i++)
scanf(
"%d",&a[i]);
for(
int i=
1;i<=n;i++){f[i]=search(a[i])+
1;vis[f[i]]=min(vis[f[i]],a[i]);}
for(
int i=
1;i<n;i++)f[n]=max(f[n],f[i]);
printf(
"%d\n",f[n]);}
}
方法二:
線段樹 (按照權值建) 查詢前一段中的最大值。。并插入當前的值,,
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,cases,a[
100050],f[
100050],xx,tree[
666666];
void insert(
int l,
int r,
int pos){
if(l==r){tree[pos]=f[xx];
return;}
int mid=(l+r)>>
1,lson=pos<<
1,rson=pos<<
1|
1;
if(mid<a[xx])insert(mid+
1,r,rson);
else insert(l,mid,lson);tree[pos]=max(tree[lson],tree[rson]);
}
int query(
int l,
int r,
int pos){
if(r<=a[xx])
return tree[pos];
int mid=(l+r)>>
1;
if(mid<a[xx])
return max(query(l,mid,pos<<
1),query(mid+
1,r,pos<<
1|
1));
else return query(l,mid,pos<<
1);
}
int main(){
scanf(
"%d",&cases);
while(cases--){
memset(tree,
0,
sizeof(tree));
memset(f,
0,
sizeof(f));
scanf(
"%d",&n);
for(
int i=
1;i<=n;i++)
scanf(
"%d",&a[i]);
for(xx=
1;xx<=n;xx++){f[xx]=query(
1,n,
1)+
1;insert(
1,n,
1);}
for(
int i=
1;i<n;i++)f[n]=max(f[n],f[i]);
printf(
"%d\n",f[n]);}
}
轉載于:https://www.cnblogs.com/SiriusRen/p/6532290.html
總結
以上是生活随笔為你收集整理的POJ 1631 nlogn求LIS的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。