BZOJ4282 : 慎二的隨機數列

Claris發表於2015-10-01

首先在開頭加上-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(n\log^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;
}

  

相關文章