暴力dp
j<i,max[j]<a[i],min[i]>a[j]dp[i]=dp[j]+1
j
<
i
,
m
a
x
[
j
]
<
a
[
i
]
,
m
i
n
[
i
]
>
a
[
j
]
d
p
[
i
]
=
d
p
[
j
]
+
1
for(int j=1; j<i; ++j)
if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次
dp[i]=max{dp[j]+1}; for(int j=1; j<i; ++j) if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次 dp[i]=max{dp[j]+1};
if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次
dp[i]=max{dp[j]+1}; for(int j=1; j<i; ++j) if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次 dp[i]=max{dp[j]+1};
所以把dp值当权值,转换为二维的点,树套树就完了
#include<cstdio>
#include<iostream>
using namespace std;
const int M=401000;
int n,m,mi[10*M],ma[10*M],a[10*M],cnt,root[10*M],ans,N;
struct xd_tree{
int maxn,ls,rs;
}t[40*M];
void modify(int &o,int l,int r,int id,int d){
if(!o) o=++cnt;
t[o].maxn=max(d,t[o].maxn);
if(l>=r) return ;
int mid=(l+r)>>1;
if(id<=mid)modify(t[o].ls,l,mid,id,d);
else modify(t[o].rs,mid+1,r,id,d);
}
int query(int o,int l,int r,int id){
if(l==r) return t[o].maxn;
int mid=(l+r)>>1;
if(id<=mid) return query(t[o].ls,l,mid,id);
else return max(t[t[o].ls].maxn,query(t[o].rs,mid+1,r,id));
}
void add(int x,int pos,int val){for(x;x<=N;x+=x&-x) modify(root[x],1,N,pos,val);}
int ask(int x,int pos){int ans=0;for(x;x;x-=x&-x) ans=max(query(root[x],1,N,pos),ans); return ans;}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),mi[i]=a[i],ma[i]=a[i];
for(int i=1,x,y;i<=m;i++){scanf("%d%d",&x,&y);
mi[x]=min(y,mi[x]);ma[x]=max(ma[x],y);N=max(N,ma[x]);
}
for(int i=1;i<=n;i++){
int now=ask(mi[i],a[i])+1;
add(a[i],ma[i],now);
ans=max(now,ans);
}
printf("%d",ans);
}