题目描述
给定一个长度为N的序列S,S的每个元素pi是一个二元组(xi,yi),定义pi<pj当且仅当xi<xj并且yi<yj,求S的最长上升子序列长度
输入格式
第一行一个N,表示一共有N个元素
接下来有N行,每行包含两个正整数xi,yi
输出格式
输出一行一个整数,代表序列S的最长上升子序列的长度
一道很好的模板题,比较入门吧
CDQ分治+线段树/树状数组维护最大值就好了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 struct nasm{ 6 int x,y,z; 7 }a[100000]; 8 int f[1000000]; 9 int tr[1000000]; 10 int tmp[100000]; 11 int n; 12 bool cmp(nasm g,nasm u) 13 { 14 return g.y<u.y; 15 } 16 bool cmq(nasm g,nasm u) 17 { 18 return g.x<u.x; 19 } 20 void updt(int pi,int v,int l,int r,int spc) 21 { 22 if(l==r) 23 { 24 tr[spc]=v==0?v:max(v,tr[spc]); 25 return ; 26 } 27 int m=(l+r)>>1; 28 if(pi<=m) 29 updt(pi,v,l,m,spc<<1); 30 else 31 updt(pi,v,m+1,r,spc<<1|1); 32 tr[spc]=max(tr[spc<<1],tr[spc<<1|1]); 33 } 34 int ask(int ll,int rr,int l,int r,int spc) 35 { 36 if(ll>rr)return 0; 37 if(l>=ll&&r<=rr)return tr[spc]; 38 int m=(l+r)>>1; 39 if(m>=rr)return ask(ll,rr,l,m,spc<<1); 40 if(m<ll)return ask(ll,rr,m+1,r,spc<<1|1); 41 return max(ask(ll,rr,l,m,spc<<1),ask(ll,rr,m+1,r,spc<<1|1)); 42 } 43 void wrk(int l,int r) 44 { 45 int mid=(l+r)>>1; 46 sort(a+l,a+mid+1,cmp); 47 sort(a+mid+1,a+r+1,cmp); 48 for(int i=l,j=mid+1;j<=r;j++) 49 { 50 for(;a[i].y<a[j].y&&i<=mid;i++) 51 updt(a[i].z,f[a[i].x],1,n,1); 52 f[a[j].x]=max(f[a[j].x],ask(1,a[j].z-1,1,n,1)+1); 53 } 54 for(int i=l;i<=mid;i++)updt(a[i].z,0,1,n,1); 55 sort(a+mid+1,a+r+1,cmq); 56 } 57 void cdq(int l,int r) 58 { 59 if(l==r) 60 return ; 61 int mid=(l+r)>>1; 62 cdq(l,mid); 63 wrk(l,r); 64 cdq(mid+1,r); 65 66 } 67 int erf(int l,int r,int aim) 68 { 69 if(l==r)return l; 70 int m=(l+r)>>1; 71 if(aim<=tmp[m]) 72 return erf(l,m,aim); 73 return erf(m+1,r,aim); 74 } 75 int main() 76 { 77 scanf("%d",&n); 78 for(int i=1;i<=n;i++) 79 { 80 scanf("%d%d",&a[i].y,&a[i].z); 81 f[i]=1; 82 a[i].x=i; 83 tmp[i]=a[i].z; 84 } 85 sort(tmp+1,tmp+n+1); 86 for(int i=1;i<=n;i++) 87 a[i].z=erf(1,n,a[i].z); 88 cdq(1,n); 89 int ans=0; 90 for(int i=1;i<=n;i++) 91 ans=max(ans,f[i]); 92 printf("%d ",ans); 93 return 0; 94 }