codevs 1576 最长上升子序列的线段树优化

题目:codevs 1576 最长严格上升子序列

链接:http://codevs.cn/problem/1576/

 

优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] 。根据数星星的经验,一个点一个点更新可以解决1到i-1的问题,然后线段树是维护最大值,那么A[j]<A[i]的条件就用查询区间保证,即查询:1到A[i]的f[i]最大值。为了不溢出,因此需要离散化。

 

附代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 using namespace std;
 5 const int maxn=5010;
 6 
 7 int f[maxn],n,maxv[maxn*4];
 8 
 9 struct u
10 {
11     int v,r;
12     bool operator <(const u &rhs) const
13     {
14         return v<rhs.v;
15     }
16 }A[maxn];
17 
18 bool cmp(u a,u b)
19 {
20     return a.r<b.r;
21 }
22 
23 int p,v;
24 void update(int o,int L,int R)
25 {
26     if(L==R) maxv[o]=v;
27     else
28     {
29         int M=(L+R)/2;
30         if(p<=M) update(o*2,L,M); else update(o*2+1,M+1,R);
31         maxv[o]=max(maxv[o*2],maxv[o*2+1]);
32     } 
33 }
34 
35 int y1,y2,ans;
36 void query(int o,int L,int R)
37 {
38     if(y1<=L && R<=y2) ans=max(ans,maxv[o]);
39     else
40     {
41         int M=(L+R)/2;
42         if(y1<=M) query(o*2,L,M);
43         if(y2>M) query(o*2+1,M+1,R);
44     }
45 }
46 
47 int main()
48 {
49     cin>>n;
50     for(int i=1;i<=n;i++)
51     {
52         cin>>A[i].v;
53         f[i]=1;
54         A[i].r=i;
55     }
56     
57     sort(A+1,A+n+1);
58     for(int i=1;i<=n;i++) A[i].v=i;
59     sort(A+1,A+n+1,cmp);
60 
61     p=A[1].v,v=1;
62     update(1,1,n);
63     for(int i=2;i<=n;i++)
64     {
65         y1=1,y2=A[i].v,ans=0;        
66         query(1,1,n);
67         f[i]=ans+1;
68         p=A[i].v,v=f[i];
69         update(1,1,n);
70     }
71     cout<<f[n];
72     return 0;
73 }

 

posted @ 2017-01-06 20:59  Frank的成长之路  阅读(210)  评论(0编辑  收藏  举报