lis基本解法
O(n^2)
for(int i = 0;i < n;i++)
for(int j = i+1;j < n;j++)
if(a[i] < a[j]) dp[j] = max(dp[i]+1,dp[j]);
课设利用lis解决合唱队形,直接基本O(n^2)莽过。(洛谷P1091的100的数据n方轻松莽过。。。
//
// main.cpp
// sing
//
// Created by 陈冉飞 on 2019/12/10.
// Copyright © 2019 陈冉飞. All rights reserved.
//
#include <iostream>
using namespace std;
#define maxn 10010
int a[maxn],n,dp1[maxn],dp2[maxn],ans;
#include <cstring>
#define cl(a,b) memset(a,b,sizeof(a))
int main(int argc, const char * argv[]) {
// while (~scanf("%d",&n)) {
scanf("%d",&n);
cl(a,0);cl(dp1, 0);cl(dp2, 0);
for (int i = 0; i < n; i++) {scanf("%d",&a[i]);dp1[i] = dp2[i] =1;}
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
if (a[i] > a[j]) dp1[i] = max(dp1[j]+1,dp1[i]);
for (int i = n-2; i >=0; i--)
for (int j = n-1; j >i; j--)
if (a[j] < a[i]) dp2[i] = max(dp2[j]+1,dp2[i]);
for (int i = 0; i < n; i++)
if (ans < (dp1[i]+dp2[i])) ans = dp1[i]+dp2[i];
printf("\n\n");
for ( int i = 0; i < n; i++) printf("%d ",dp1[i]);
printf("\n\n");
printf("%d\n",n-ans+1);
// }
return 0;
}
好了。言归正传,lis利用二分nlogn……
用一个数组其实这个数组没有什么特殊的含义,来记录对应索引处的长度的lis的最小末尾,利用这个末尾可以插入数据。
插入数据利用二分插入,插入到合适的位置。
二分插入logn,n个数,所以最后是nlogn
//
// main.cpp
// binary_lis
//
// Created by 陈冉飞 on 2019/12/15.
// Copyright © 2019 陈冉飞. All rights reserved.
//
#include <iostream>
using namespace std;
#define maxn 10010
int a[maxn],ans[maxn],n,len;
#include <cstring>
#define cl(a,b) memset(a,b,sizeof(a))
int binary(int t){
int l = 0,r = len,mid;
while (l < r) {
mid = (l+r)>>1;
if (a[t] < ans[mid]) r = mid;
else l = mid+1;
}
return l;
}
int binary_lis(){
len = 1;ans[1] = a[1];
for (int i = 2; i <= n; i++)
if (a[i] > ans[len]) ans[++len] = a[i];
else ans[binary(i)] = a[i];
// for (int i = 1; i <= len; i++) printf("%d ",ans[i]);
return len;
}
int main(int argc, const char * argv[]) {
while (~scanf("%d",&n)) {
// init
cl(a,0);
for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
printf("%d",binary_lis());
}
return 0;
}
利用二分没有可扩展性,也就是只能算出整个长度的最大递增。
然后通过树状数组可以得到整个的每个段的lis
//
// main.cpp
// tree_lis
//
// Created by 陈冉飞 on 2019/12/15.
// Copyright © 2019 陈冉飞. All rights reserved.
//
#include <iostream>
using namespace std;
#include <cstring>
#define cl(a,b) memset(a,b,sizeof(a))
#define maxn 10010
int a[maxn],b[maxn],dp1[maxn],f[maxn],n,t,ans,dp2[maxn];
#include <algorithm>
#define lowbit(x) x&-x
void modify(int x,int p){
for (; x <= t ; x += lowbit(x)) f[x] = max(f[x],p);
}
int get_max(int x){
int tem = 0;
for (; x; x -= lowbit(x)) tem = max(tem,f[x]);
return tem;
}
int main(int argc, const char * argv[]) {
while (~scanf("%d",&n)) {
for (int i = 1; i <= n; i++) scanf("%d",&a[i]),b[i] = a[i];
sort(b+1,b+n+1);
t = unique(b+1,b+n+1)-b-1;
for (int i = 1; i <= n; i++) a[i] = lower_bound(b+1,b+t+1,a[i])-b;
for (int i = 1; i <= n; i++) {
dp1[i] = get_max(a[i]-1)+1;
ans = max(ans,dp1[i]);
modify(a[i],dp1[i]);
}
for (int i = 1; i <= n; i++) printf("%d ",dp1[i]);
printf("%d\n",ans);
}
return 0;
}