[TJOI&HEOI2016]seq/[JZOJ4606]序列

来源:互联网 发布:手机上传淘宝主图视频 编辑:程序博客网 时间:2024/06/10 03:11

题目大意

一个长度为n的序列a,有m种变换可能,将ax变为y
现在你需要求出一个子序列,使得不管发生哪种变换(最多只会发生一种变换,可能不发生),该序列都是不下降的。
1n,m,ai,y105


题目分析

定义mxi为位置i上的数最大变化值,mii为最小变化值。
动态规划

fi=maxj<i,mxjai,ajmii{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;}
0 0
原创粉丝点击