题目大意:求一个由二元组组成最长序列,二元组的相对位置不变,并且满足对于数列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;
}