题目大意:求一个由二元组组成最长序列,二元组的相对位置不变,并且满足对于数列a中任意一个数字
aia_{i}ai都是极大值或者极小值。
简单的dp,但是会超时,dp代码如下
#inc#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int a[100005][3]; int dp[100005]; int main() { int n; int ans; while(scanf("%d",&n)!=EOF){ memset(a,0,sizeof(a)); for(int i=0;i<n;i++){ scanf("%d%d",&a[i][0],&a[i][1]); a[i][2]=a[i][0]>a[i][1]?0:1; //如果第一个数大则为0,第二个数为1 } ans=0; for(int i=0;i<n;i++){ dp[i]=1; for(int j=0;j<i;j++){ if(a[j][2]==1&&a[i][2]==1&&a[j][1]>a[i][0]){ dp[i]=max(dp[j]+1,dp[i]); } if(a[j][2]==0&&a[i][2]==0&&a[i][0]>a[j][1]){ dp[i]=max(dp[j]+1,dp[i]); } } ans=max(ans,dp[i]); } printf("%d\n",ans); } }那么我们可以利用线段树来吧第二段for循环简化。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int treex[100005*4]; int treey[100005*4]; int x[100005]; //x》y 储存 y int y[100005]; int crt[200055]; int cmp(int x,int y) { return x<y; } int y_query(int p,int l,int r,int x,int y) //从l到r里找x到y的最大值 { // printf("%d %d %d %d %d\n",p,l,r,x,y); if(x<=l&&r<=y){ return treey[p]; } int mid=(l+r)/2; if(mid>=y){ return y_query(p*2,l,mid,x,y); } else if(x>mid){ return y_query(p*2+1,mid+1,r,x,y); } else{ return max(y_query(p*2,l,mid,x,mid),y_query(p*2+1,mid+1,r,mid+1,y)); } } int x_query(int p,int l,int r,int x,int y) //从l到r里找x到y的最大值 { // printf("%d %d %d %d %d\n",p,l,r,x,y); if(x<=l&&r<=y){ return treex[p]; } int mid=(l+r)/2; if(mid>=y){ return x_query(p*2,l,mid,x,y); } else if(x>mid){ return x_query(p*2+1,mid+1,r,x,y); } else{ return max(x_query(p*2,l,mid,x,mid),x_query(p*2+1,mid+1,r,mid+1,y)); } } void x_change(int p,int l,int r,int x,int c) { if(l==r){ treex[p]=c; return ; } int mid=(l+r)/2; if(x<=mid){ x_change(p*2,l,mid,x,c); } else{ x_change(p*2+1,mid+1,r,x,c); } treex[p]=max(treex[p*2],treex[p*2+1]); } void y_change(int p,int l,int r,int x,int c) { if(l==r){ treey[p]=c; return ; } int mid=(l+r)/2; if(x<=mid){ y_change(p*2,l,mid,x,c); } else{ y_change(p*2+1,mid+1,r,x,c); } treey[p]=max(treey[p*2],treey[p*2+1]); } int main() { int n,ans; while(scanf("%d",&n)!=EOF){ int t=0; crt[t++]=-2; crt[t++]=-1; crt[t++]=1000000000+1; for(int i=0;i<n;i++){ scanf("%d%d",&x[i],&y[i]); crt[t++]=x[i]; crt[t++]=y[i]; } sort(crt,crt+(n*2),cmp); int m=unique(crt,crt+(n*2))-crt; ans=0; for(int i=0;i<m;i++){ // printf("%d %d \n",i,crt[i]); } for(int i=0;i<n;i++){ int s_x=lower_bound(crt,crt+m,x[i])-crt; int s_y=lower_bound(crt,crt+m,y[i])-crt; if(x[i]>y[i]){ //第一个数大,找y比x[i]要小的最大长度 int ax=x_query(1,1,m,1,s_x-1)+1; x_change(1,1,m,s_y,ax); //printf("%d %d\n",i,ax); } else{ int ay=y_query(1,1,m,s_x+1,m)+1;//第二个数大,找y比x[i]要大的最大长度 y_change(1,1,m,s_y,ay); // printf("%d %d\n",i,ay); } } printf("%d\n",max(treex[1],treey[1])); } return 0; }