正题
题目链接:https://www.luogu.com.cn/problem/P4093
题目大意
nnn个数字,每次有一个数字可能和原序列不同,但最多只有一个不同。
求所有情况下都满足的最长不降子序列
解题思路
定义maximax_imaxi表示位置iii的最大数,minimin_imini表示位置iii的最小数。
然后有转移方程fi=max{fj}+1(ai≥maxj,mini≥aj)f_i=max\{f_j\}+1(a_i\geq max_j,min_i\geq a_j)fi=max{fj}+1(ai≥maxj,mini≥aj)
可以发现这是一个三维偏序,用cdq分治+树状数组即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lowbit(x) (x&-x)
using namespace std;
const int N=1e5+10;
int n,m,a[N],b[N],s[N];
int t[N],p[N],f[N],ans;
bool cmp1(int x,int y)
{return b[x]<b[y];}
bool cmp2(int x,int y)
{return a[x]<a[y];}
void Change(int x,int val){while(x<=n){t[x]=max(t[x],val);x+=lowbit(x);}return;
}
void Clear(int x){while(x<=n){t[x]=0;x+=lowbit(x);}return;
}
int Ask(int x){int ans=0;while(x){ans=max(ans,t[x]);x-=lowbit(x);}return ans;
}
void cdq(int l,int r){if(l==r){f[l]=max(f[l],1);return;}int mid=(l+r)>>1;cdq(l,mid);for(int i=l;i<=r;i++)p[i]=i;sort(p+l,p+mid+1,cmp1);sort(p+mid+1,p+r+1,cmp2);int k=l;for(int i=mid+1;i<=r;i++){while(k<=mid&&b[p[k]]<=a[p[i]])Change(a[p[k]],f[p[k]]),k++;f[p[i]]=max(f[p[i]],Ask(s[p[i]])+1);}for(int i=l;i<=mid;i++)Clear(a[i]);cdq(mid+1,r);return;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=s[i]=a[i];for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);b[x]=max(b[x],y);s[x]=min(s[x],y);}cdq(1,n);for(int i=1;i<=n;i++)ans=max(ans,f[i]);printf("%d",ans);
}