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

京公网安备 11010502036488号