BZOJ2090 [POI2010]MOT-Monotonicity 2
Description
给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
求出L的最大值。
如果没有s数组的限制,这道题就是一道简单的打导弹,所以我们任然考虑DP。我们考虑证明决策单调性。
考虑一个序列的末尾q与一个新的数p,下面证明p代替q,答案不会更优秀。
考虑s序列<><,即q<p,若p代替q,答案会更优,则有数z,t,满足p<z>t。但是注意q<p,所以一定有q<z>t。故答案不会更优。
那么线段树优化DP即可。
#include<bits/stdc++.h> using namespace std; const int N=1000005; int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } struct Ans{ int a,pre; }; struct Tre{ int a[N*4+5],pre[N*4+5]; void insert(int p,int l,int r,int x,int v,int o){ if (l==r){pre[p]=o; a[p]=v; return;} int mid=(l+r)>>1; if (x<=mid) insert(p*2,l,mid,x,v,o); else insert(p*2+1,mid+1,r,x,v,o); int ls=p*2; int rs=ls+1; if (a[ls]>=a[rs]) {a[p]=a[ls]; pre[p]=pre[ls];} else{a[p]=a[rs]; pre[p]=pre[rs];} } Ans query(int p,int l,int r,int ql,int qr){ Ans q; q.a=0; q.pre=0; if (qr<ql) return q; if (ql<=l&&qr>=r){ Ans b; b.a=a[p]; b.pre=pre[p]; return b;} int mid=(l+r)>>1; if (ql<=mid) {Ans b=query(p*2,l,mid,ql,qr); if (b.a>q.a) q=b;} if (qr>mid){Ans b=query(p*2+1,mid+1,r,ql,qr); if (b.a>q.a) q=b;} return q; } }T1,T2; int a[N],s[N],f[N],fr[N],qs[N*2],qsf[N*2],sol[N]; void Pri(int x){ if (x==0) return; sol[++sol[0]]=x; x=fr[x]; Pri(x); } int main(){ int mx=0,mn=1000000,n=read(),k=read(); for (int i=1;i<=n;i++) { a[i]=read(); if (a[i]>mx) mx=a[i];} char c[N]; for (int i=1;i<=k;i++){ cin>>c; if (c[0]=='<') s[i]=0; if (c[0]=='>') s[i]=1; if (c[0]=='=') s[i]=2; } for (int i=1;i<=n;i++){ f[i]=qs[a[i]]+1; fr[i]=qsf[a[i]]; Ans a1=T1.query(1,1,mx,1,a[i]-1); Ans a2=T2.query(1,1,mx,a[i]+1,mx); Ans c; if (a1.a>a2.a) c=a1; else c=a2; if (c.a+1>f[i]) f[i]=c.a+1,fr[i]=c.pre; int fh=s[(f[i]-1)%k+1]; if (fh==2) qs[a[i]]=f[i],qsf[a[i]]=i; if (fh==0) T1.insert(1,1,mx,a[i],f[i],i); if (fh==1) T2.insert(1,1,mx,a[i],f[i],i); } Ans ans; ans.a=0; for (int i=1;i<=n;i++) if (f[i]>ans.a) ans.a=f[i],ans.pre=i; Pri(ans.pre); printf("%d\n",ans.a); for (int i=ans.a;i>=1;i--){ printf("%d ",a[sol[i]]); } printf("\n"); return 0; }

浙公网安备 33010602011771号