POJ 1631 Bridging signals
事实上就是求最长上升子序列的长度。用nlogn的写法。我用了线段树。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=40000+10; int dp[maxn]; int a[maxn]; int T,n,ans,f; struct SegTree { int MAX; }s[4*maxn]; void pushUp(int rt) { s[rt].MAX=max(s[2*rt].MAX,s[2*rt+1].MAX); } void build(int l,int r,int rt) { s[rt].MAX=0; if(l==r) return; int m=(l+r)/2; build(l,m,2*rt); build(m+1,r,2*rt+1); } void update(int pos,int val,int l,int r,int rt) { if(l==r) { s[rt].MAX=val; return; } int m=(l+r)/2; if(pos<=m) update(pos,val,l,m,2*rt); else update(pos,val,m+1,r,2*rt+1); pushUp(rt); } void quary(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { f=max(f,s[rt].MAX); return; } int m=(l+r)/2; if(L<=m) quary(L,R,l,m,2*rt); if(R>m) quary(L,R,m+1,r,2*rt+1); } int main() { // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); scanf("%d",&T); while(T--) { scanf("%d",&n); ans=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); for(int i=1;i<=n;i++) { f=0; if(a[i]==1) f=0; else quary(1,a[i]-1,1,n,1); dp[i]=f+1; update(a[i],dp[i],1,n,1); ans=max(ans,dp[i]); } printf("%d\n",ans); } return 0; }