正题
题目链接:https://www.luogu.com.cn/problem/P4093
题目大意
n n n个数字,每次有一个数字可能和原序列不同,但最多只有一个不同。
求所有情况下都满足的最长不降子序列
解题思路
定义 m a x i max_i maxi表示位置 i i i的最大数, m i n i min_i mini表示位置 i i i的最小数。
然后有转移方程 f i = m a x { f j } + 1 ( a i ≥ m a x j , m i n i ≥ a j ) 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分治+树状数组即可。
c o d e code code
#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);
}