BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 分治
原文链接http://www.cnblogs.com/zhouzhendong/p/8672434.html
题目传送门 - BZOJ4553
题目传送门 - 洛谷P4093
题解
设$Li$表示第$i$个位置最小值,$Ri$表示最大值$vi$表示原值。
那么如果$i$能到$j$这个位置,则满足:
$i<j$
$rj\leq xi$
$xi\leq li$
于是CDQ分治水过。
代码
#include <bits/stdc++.h> using namespace std; const int N=100005; struct Node{ int id,v,L,R,res,x,y; void get(){ scanf("%d",&v),L=R=v,res=1; } }a[N]; bool cmp(Node a,Node b){ if (a.x!=b.x) return a.x<b.x; if (a.y!=b.y) return a.y<b.y; return a.id<b.id; } bool cmpid(Node a,Node b){ return a.id<b.id; } int n,m,tree[N]; int lowbit(int x){ return x&-x; } void add(int x,int y){ for (;x<=100000;x+=lowbit(x)) tree[x]=max(tree[x],y); } void clr(int x){ for (;x<=100000;x+=lowbit(x)) tree[x]=0; } int sum(int x){ int ans=0; for (;x>0;x-=lowbit(x)) ans=max(ans,tree[x]); return ans; } void CDQ(int L,int R){ if (L==R) return; int mid=(L+R)>>1; CDQ(L,mid); for (int i=L;i<=mid;i++) a[i].x=a[i].R,a[i].y=a[i].v; for (int i=mid+1;i<=R;i++) a[i].x=a[i].v,a[i].y=a[i].L; sort(a+L,a+R+1,cmp); for (int i=L;i<=R;i++) if (a[i].id<=mid) add(a[i].y,a[i].res); else a[i].res=max(a[i].res,sum(a[i].y)+1); for (int i=L;i<=R;i++) if (a[i].id<=mid) clr(a[i].y); sort(a+L,a+R+1,cmpid); CDQ(mid+1,R); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) a[i].get(),a[i].id=i; for (int i=1,x,y;i<=m;i++){ scanf("%d%d",&x,&y); a[x].L=min(a[x].L,y); a[x].R=max(a[x].R,y); } memset(tree,0,sizeof tree); CDQ(1,n); int ans=0; for (int i=1;i<=n;i++) ans=max(ans,a[i].res); printf("%d",ans); return 0; }