1. 程式人生 > >「luogu4093」[HEOI2016/TJOI2016]序列

「luogu4093」[HEOI2016/TJOI2016]序列

ans sort AC struct class 狀態 col print lowbit

寫出dp方程,可以發現轉移要滿足一個三維偏序,那麽可以處理三維偏序的方法優化。

CDQ分治:

  cdq分治和樹狀數組是好夥伴~

  註意分治的順序,要保證先求解出所有前驅狀態。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100010;
 4 int n,m,dp[N],maxn;
 5 struct Node{
 6     int a,maxv,minv,id;
 7 }node[N];
 8 int cmpa(const Node& x,const Node& y){return
x.a<y.a;} 9 int cmpv(const Node& x,const Node& y){return x.maxv<y.maxv;} 10 int cmpid(const Node& x,const Node& y){return x.id<y.id;} 11 int bit[N]; 12 inline int lowbit(int k){return k&(-k);} 13 inline void change(int k,int x){while(k<=maxn) bit[k]=max(bit[k],x),k+=lowbit(k);return
;} 14 inline int que(int k){ 15 int ans=0; 16 while(k) ans=max(bit[k],ans),k-=lowbit(k); 17 return ans; 18 } 19 inline void reset(int k){ 20 while(k<=maxn){ 21 if(!bit[k]) return; 22 bit[k]=0,k+=lowbit(k); 23 } 24 return; 25 } 26 void cdq(int l,int r){ 27 if
(l>=r) return; 28 int mid=(l+r)>>1; 29 cdq(l,mid); 30 sort(node+l,node+mid+1,cmpv);sort(node+mid+1,node+r+1,cmpa); 31 int pl=l,pr=mid+1; 32 while(pl<=mid&&pr<=r){ 33 if(node[pl].maxv<=node[pr].a){ 34 change(node[pl].a,dp[node[pl].id]); 35 pl++; 36 }else{ 37 dp[node[pr].id]=max(dp[node[pr].id],que(node[pr].minv)+1); 38 pr++; 39 } 40 } 41 while(pr<=r){ 42 dp[node[pr].id]=max(dp[node[pr].id],que(node[pr].minv)+1); 43 pr++; 44 } 45 for(int i=l;i<=mid;i++) reset(node[i].a); 46 sort(node+l,node+r+1,cmpid); 47 cdq(mid+1,r); 48 return; 49 } 50 int main(){ 51 int t1,t2; 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++) scanf("%d",&node[i].a),node[i].maxv=node[i].minv=node[i].a,node[i].id=i,dp[i]=1,maxn=max(maxn,node[i].a); 54 while(m--){ 55 scanf("%d%d",&t1,&t2); 56 maxn=max(maxn,t2); 57 node[t1].maxv=max(node[t1].maxv,t2); 58 node[t1].minv=min(node[t1].minv,t2); 59 } 60 cdq(1,n); 61 int ans=0; 62 for(int i=1;i<=n;i++) ans=max(ans,dp[i]); 63 printf("%d",ans); 64 return 0; 65 }

樹套樹:

「luogu4093」[HEOI2016/TJOI2016]序列