题目大意
一个长度为n的序列
现在你需要求出一个子序列,使得不管发生哪种变换(最多只会发生一种变换,可能不发生),该序列都是不下降的。
题目分析
定义mxi为位置i上的数最大变化值,
动态规划
fi=maxj<i,mxj≤ai,aj≤mii{fj}+1
第一个约束顺序解决。
第二三个约束看成二维平面上的点,树套树解决,空间要卡好,不要炸了。我码了棵树状数组套线段树,时间复杂度O(nlog22n),空间复杂度远小于上界O(nlog22n)。
然而第二个约束可以使用cdq分治解决,虽然时间复杂度也是O(nlog22n),但常数较树套树少很多,而且空间复杂度O(n)。
代码实现
#include <iostream>
#include <cstdio>
#include <cctype>
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int S=10050000;
const int N=100005;
const int A=100000;
const int LGA=17;
int tmp[LGA];
int lowbit(int x){return x&-x;}
struct chairman_tree
{
int son[S][2],v[S];
int root[A+10];
int tot;
int newnode(){return ++tot;}
int query(int *rt,int st,int en,int l,int r)
{
int i,ret=0;
if (st==l&&en==r)
{
for (i=1;i<=rt[0];i++) ret=max(v[rt[i]],ret);
return ret;
}
int mid=l+r>>1,t[LGA];
t[0]=rt[0];
if (en<=mid)
{
for (i=1;i<=rt[0];i++) t[i]=son[rt[i]][0];
return query(t,st,en,l,mid);
}
else
if (mid+1<=st)
{
for (i=1;i<=rt[0];i++) t[i]=son[rt[i]][1];
return query(t,st,en,mid+1,r);
}
else
{
for (i=1;i<=rt[0];i++) t[i]=son[rt[i]][0];
ret=query(t,st,mid,l,mid);
for (i=1;i<=rt[0];i++) t[i]=son[rt[i]][1];
ret=max(query(t,mid+1,en,mid+1,r),ret);
return ret;
}
}
void modify(int *rt,int x,int l,int r,int edit)
{
int i,ret=0;
for (i=1;i<=rt[0];i++)
{
if (!rt[i]) rt[i]=newnode();
v[rt[i]]=max(v[rt[i]],edit);
}
if (l==r) return;
int mid=l+r>>1,t[LGA];
t[0]=rt[0];
if (x<=mid)
{
for (i=1;i<=rt[0];i++) t[i]=son[rt[i]][0];
modify(t,x,l,mid,edit);
for (i=1;i<=rt[0];i++) son[rt[i]][0]=t[i];
}
else
{
for (i=1;i<=rt[0];i++) t[i]=son[rt[i]][1];
modify(t,x,mid+1,r,edit);
for (i=1;i<=rt[0];i++) son[rt[i]][1]=t[i];
}
}
}t;
int a[N],mi[N],mx[N],f[N];
int n,m,ans;
void dp()
{
for (int i=1,j,l;i<=n;i++)
{
for (l=mi[i],tmp[0]=0;l;l-=lowbit(l)) tmp[++tmp[0]]=t.root[l];
f[i]=t.query(tmp,1,a[i],1,A)+1;
ans=max(ans,f[i]);
for (l=a[i],tmp[0]=0;l<=A;l+=lowbit(l)) tmp[++tmp[0]]=t.root[l];
t.modify(tmp,mx[i],1,A,f[i]);
for (l=a[i],j=1;l<=A;j++,l+=lowbit(l)) t.root[l]=tmp[j];
}
}
int main()
{
freopen("sequence.in","r",stdin),freopen("sequence.out","w",stdout);
n=read(),m=read();
for (int i=1;i<=n;i++) mi[i]=mx[i]=a[i]=read();
for (int i=1,x,y;i<=m;i++)
{
x=read(),y=read();
mi[x]=min(mi[x],y),mx[x]=max(mx[x],y);
}
dp();
printf("%d\n",ans);
fclose(stdin),fclose(stdout);
return 0;
}