codevs 1576 最长严格上升子序列
时间限制: 1 s
空间限制: 256000 KB
题目等级 : 黄金 Gold
题目描述 Description
给一个数组a1, a2 ... an,找到最长的上升降子序列ab1<ab2< .. <abk,其中b1<b2<..bk。
输出长度即可。
输入描述 Input Description
第一行,一个整数N。
第二行 ,N个整数(N < = 5000)
输出描述 Output Description
输出K的极大值,即最长不下降子序列的长度
样例输入 Sample Input
5
9 3 6 2 7
样例输出 Sample Output
3
此题的转移公式很简单
要注意到 这个max函数 其实是有A[k]<A[x] 这个限制要求的 所以我们真正需要查询的最大值其实在0----A[x]中 所以我们可以利用线段树做查询
每次计算出来的值我们可以反向插入到线段树中做记录
第一版的代码没有全部通过 原因是数字超出了线段树可以表示的范围,这个时候离散化就可以派上用场了我们先看第一版残缺代码
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 const int maxn=100000; 9 const int maxm=5000000; 10 #define lson l,mid,rt<<1 11 #define rson mid+1,r,rt<<1|1 12 #define lrt rt<<1 13 #define rrt rt<<1|1 14 #define getmid int mid=(r+l)/2 15 16 17 int n,maxx[maxn*4],tp,ans; 18 19 void update(int l,int r,int rt,int a,int b) 20 { 21 if(a<=l && a>=r) 22 { 23 maxx[rt]=max(maxx[rt],b); 24 return; 25 } 26 getmid; 27 if(a<=mid) update(lson,a,b); 28 if(a>mid) update(rson,a,b); 29 maxx[rt]=max(maxx[rt],max(maxx[lrt],maxx[rrt])); 30 } 31 32 33 int query(int l,int r,int rt,int a,int b) 34 { 35 if(a<=l && b>=r) 36 { 37 return maxx[rt]; 38 } 39 getmid; 40 int ans=0; 41 if(a<=mid){ 42 ans=max(ans,query(lson,a,b)); 43 } 44 if(b>mid){ 45 ans=max(ans,query(rson,a,b)); 46 } 47 return ans; 48 } 49 50 int main() 51 { 52 scanf("%d",&n); 53 for(int i=1;i<=n;i++) 54 { 55 scanf("%d",&tp); 56 int t=query(0,maxn,1,1,tp-1)+1; 57 ans=max(ans,t); 58 update(0,maxn,1,tp,t); 59 } 60 printf("%d",ans); 61 return 0; 62 }
这个代码没用离散化 所以得分是悲剧的
我们注意到那个过不了的数据是907741 超出范围了 所以我们要用离散化技术把元数据处理成等价的小数据
最终正确的代码如下
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int maxn=100000; const int maxm=5000000; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define getmid int mid=(r+l)/2 struct u { int a,id; }; u A[maxn]; bool cmp(u a,u b){ return a.a<b.a; } int n,maxx[maxn*4],B[maxn],ans; void update(int l,int r,int rt,int a,int b) { if(a<=l && a>=r) { maxx[rt]=max(maxx[rt],b); return; } getmid; if(a<=mid) update(lson,a,b); if(a>mid) update(rson,a,b); maxx[rt]=max(maxx[rt],max(maxx[lrt],maxx[rrt])); } int query(int l,int r,int rt,int a,int b) { if(a<=l && b>=r) { return maxx[rt]; } getmid; int ans=0; if(a<=mid){ ans=max(ans,query(lson,a,b)); } if(b>mid){ ans=max(ans,query(rson,a,b)); } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&A[i].a); A[i].id=i; } sort(A+1,A+1+n,cmp); int pre=A[1].a; int nk=1; B[A[1].id]=nk; for(int i=2;i<=n;i++) { if(pre!=A[i].a){ nk++; pre=A[i].a; } B[A[i].id]=nk; } for(int i=1;i<=n;i++) { int tp=query(0,maxn,1,0,B[i]-1)+1; //这里要注意 查询范围是0到B[i]-1 想一想为什么 ans=max(ans,tp); update(0,maxn,1,B[i],tp); } printf("%d",ans); return 0; }