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(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; }