BZOJ4553 [Tjoi2016&Heoi2016]序列
这题我们可以联想为普通的最长上升子序列,既f[i]=max(f[j])+1;i>j
所以这个就有了后效性,我们只关注他的左区间对答案的贡献,也就是j<=mid i>=mid+1;
所以顺序就变为了左边,中间,右边
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100005; 4 int n,m; 5 struct node 6 { 7 int l,r,id,a; 8 bool operator <(const node &b)const{ 9 if(l==b.l) 10 { 11 return r==b.r?id<b.id:r<b.r; 12 } 13 return l<b.l; 14 } 15 }q[N],p[N]; 16 int t[N],v[N],tim,f[N]; 17 inline int lowbit(int x){return x&(-x);} 18 void add(int x,int y) 19 { 20 for(;x<=N-5;x+=lowbit(x)) 21 { 22 if(v[x]!=tim) 23 { 24 v[x]=tim;t[x]=y; 25 } 26 else t[x]=max(t[x],y); 27 } 28 } 29 int get(int x) 30 { 31 int an=0;for(;x;x-=lowbit(x))if(tim==v[x])an=max(an,t[x]);return an; 32 } 33 void solve(int l,int r) 34 { 35 if(l==r){f[l]=max(f[l],1);return;} 36 int mid=l+r>>1; 37 solve(l,mid);tim++; 38 for(int i=l;i<=r;++i) 39 { 40 if(i<=mid)p[i].l=q[i].a,p[i].r=q[i].r,p[i].id=q[i].id; 41 else p[i].l=q[i].l,p[i].r=q[i].a,p[i].id=q[i].id; 42 } 43 sort(p+l,p+r+1); 44 for(int i=l;i<=r;++i) 45 { 46 if(p[i].id<=mid)add(p[i].r,f[p[i].id]); 47 else f[p[i].id]=max(f[p[i].id],get(p[i].r)+1); 48 } 49 solve(mid+1,r); 50 } 51 int main() 52 { 53 scanf("%d%d",&n,&m);int x,y; 54 for(int i=1;i<=n;++i)scanf("%d",&q[i].a),q[i].r=q[i].l=q[i].a,q[i].id=i; 55 for(int i=1;i<=m;++i) 56 { 57 scanf("%d%d",&x,&y);q[x].r=max(q[x].r,y);q[x].l=min(q[x].l,y); 58 } 59 solve(1,n);int ans=0; 60 for(int i=1;i<=n;++i)ans=max(ans,f[i]); 61 printf("%d\n",ans); 62 return 0; 63 }
LIS的dp很简单,三维偏序,max[j]<a[i] a[j]<min[i] j<i 我们分治一下,然后两边排一下序,左面按a[j]排序,右面按min[i] 排序,这样我们可以满足两维,接下俩用线段树做一下第三个偏序即可。—— by VANE
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int t[N*4],a[N],id[N],mi[N],mx[N],f[N]; bool bz[N*4]; int n,m,ans; void clear(int p) { t[p]=0;bz[p]=1; } void pushdown(int p) { if(bz[p]) { clear(p<<1); clear(p<<1|1); bz[p]=0; } } void change(int p,int l,int r,int a,int b) { if(l==r) { t[p]=max(t[p],b); return; } pushdown(p); int mid=l+r>>1; if(a<=mid) change(p<<1,l,mid,a,b); else change(p<<1|1,mid+1,r,a,b); t[p]=max(t[p<<1],t[p<<1|1]); } int query(int p,int l,int r,int a,int b) { if(l==a&&r==b) return t[p]; pushdown(p); int mid=l+r>>1; if(b<=mid) return query(p<<1,l,mid,a,b); else if(a>mid) return query(p<<1|1,mid+1,r,a,b); else return max(query(p<<1,l,mid,a,mid),query(p<<1|1,mid+1,r,mid+1,b)); } bool cmpa(int x,int y) { return a[x]<a[y]; } bool cmpmi(int x,int y) { return mi[x]<mi[y]; } void solve(int l,int r) { if(l==r) { f[l]=max(f[l],1); return; } int mid=l+r>>1; solve(l,mid); for(int i=l;i<=r;++i) id[i]=i; sort(id+l,id+1+mid,cmpa); sort(id+mid+1,id+r+1,cmpmi); clear(1); int j=l,i; for(i=mid+1;i<=r;++i) { while(j<=mid&&a[id[j]]<=mi[id[i]]) { change(1,1,n,mx[id[j]],f[id[j]]); j++; } f[id[i]]=max(f[id[i]],query(1,1,n,1,a[id[i]])+1); } solve(mid+1,r); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",a+i),mi[i]=mx[i]=a[i]; for(int i=1;i<=m;++i) { int x,y; scanf("%d%d",&x,&y); mi[x]=min(mi[x],y); mx[x]=max(mx[x],y); } solve(1,n); int ans=0; for(int i=1;i<=n;++i) ans=max(ans,f[i]); cout<<ans; }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。