• BZOJ4282 : 慎二的随机数列


    首先在开头加上-inf,结尾加上inf,最后答案减2即可。

    设s[i]为i之前未知的个数,f[i]为以i结尾的LIS,且a[i]已知,那么:

    f[i]=max(f[j]+min(s[i]-s[j],a[i]-a[j]-1))+1,其中j<i,a[j]<a[i]且a[j]已知

    将min分类讨论后可转化为三维偏序,CDQ分治+扫描线+树状数组即可,时间复杂度$O(nlog^2n)$。

    #include<cstdio>
    #include<algorithm>
    using std::sort;
    const int N=100010,inf=1000000000;
    char ch[5];
    int n,m,i,a[N],s[N],b[N],c[N],B[N],C[N<<1],f[N],g[N];
    int qa[N],qb[N],ca,cb,T,pos0[N],bit0[N],pos1[N<<1],bit1[N<<1];
    inline int cmp(int x,int y){return a[x]<a[y];}
    inline int lowerb(int x){
      int l=1,r=m,mid,t;
      while(l<=r)if(B[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    inline int lowerc(int x){
      int l=1,r=n,mid,t;
      while(l<=r)if(C[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    inline void up(int&a,int b){if(a<b)a=b;}
    inline void add0(int x,int y){for(;x<=m;x+=x&-x)if(pos0[x]<T)pos0[x]=T,bit0[x]=y;else up(bit0[x],y);}
    inline void ask0(int&t,int x){for(;x;x-=x&-x)if(pos0[x]==T)up(t,bit0[x]);}
    inline void add1(int x,int y){for(;x<=n;x+=x&-x)if(pos1[x]<T)pos1[x]=T,bit1[x]=y;else up(bit1[x],y);}
    inline void ask1(int&t,int x){for(;x;x-=x&-x)if(pos1[x]==T)up(t,bit1[x]);}
    void solve(int l,int r){
      if(l==r){
        f[l]+=s[l]+1,g[l]+=a[l];
        if(l==1)f[l]=1;
        up(f[l],g[l]);
        return;
      }
      int mid=(l+r)>>1;
      solve(l,mid);
      int i,j;
      ca=cb=0;
      for(i=l;i<=mid;i++)qa[ca++]=i;
      for(i=r;i>mid;i--)qb[cb++]=i;
      sort(qa,qa+ca,cmp),sort(qb,qb+cb,cmp);
      for(T++,i=j=0;i<cb;i++){
        while(j<ca&&a[qa[j]]<a[qb[i]]){
          add0(b[qa[j]],f[qa[j]]-s[qa[j]]);
          add1(lowerc(c[qa[j]]-1),f[qa[j]]-a[qa[j]]);
          j++;
        }
        ask0(f[qb[i]],b[qb[i]]-1);
        ask1(g[qb[i]],lowerc(c[qb[i]]));
      }
      solve(mid+1,r);
    }
    int main(){
      scanf("%d",&n);
      a[m=1]=-inf;
      while(n--){
        scanf("%s",ch);
        if(ch[0]=='N')i++;else s[++m]=i,scanf("%d",&a[m]);
      }
      s[++m]=i,a[m]=inf;
      for(n=0,i=1;i<=m;i++){
        B[i]=b[i]=a[i]-s[i];
        C[++n]=c[i]=s[i]-a[i];
        C[++n]=c[i]-1;
        f[i]=g[i]=-inf;
      }
      sort(B+1,B+m+1),sort(C+1,C+n+1);
      for(i=1;i<=m;i++)b[i]=lowerb(b[i]);
      solve(1,m);
      return printf("%d",f[m]-2),0;
    }
    

      

  • 相关阅读:
    输出三角行
    练习
    循环
    阶乘
    常量、变量、数据类型 搞错N+1次 累死
    UTF-8
    数据库事务
    Jsp的使用
    Cookie和Session
    请求转发和重定向
  • 原文地址:https://www.cnblogs.com/clrs97/p/4851537.html
Copyright © 2020-2023  润新知