[BZOJ2225][SP2371]LIS2 - Another Longest Increasing Subsequence Problem:CDQ分治+樹狀陣列
阿新 • • 發佈:2018-11-27
分析
這回試了一下三級標題,不知道效果怎麼樣?
回到正題,二維最長上升子序列......嗯,我會二維線段樹。
考慮\(CDQ\)分治,演算法流程:
先遞迴進入左子區間。
將左,右子區間按\(x\)排序。
歸併處理左右子區間,在過程中使用樹狀陣列加速\(DP\)。
還原右區間,清空樹狀陣列。
遞迴進入右子區間。
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cctype> #include <algorithm> #define lowbit(x) ((x)&(-(x))) #define rin(i,a,b) for(int i=(a);i<=(b);i++) #define rec(i,a,b) for(int i=(a);i>=(b);i--) #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt) using std::cin; using std::cout; using std::endl; typedef long long LL; inline 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<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } const int MAXN=100005; int n,b[MAXN]; int siz; int bit[MAXN]; int rev[MAXN]; struct Node{ int x,y,pos,f; Node(){ f=1; } friend bool operator < (Node x,Node y){ return x.x==y.x?x.y<y.y:x.x<y.x; } }a[MAXN],c[MAXN]; inline void Add(int x,int kk){ for(int i=x;i<=siz;i+=lowbit(i)) bit[i]=(kk==-1?0:std::max(bit[i],kk)); } inline int Ask(int x){ int ret=0; for(int i=x;i;i-=lowbit(i)) ret=std::max(ret,bit[i]); return ret; } inline bool cmp(Node x,Node y){ return x.pos<y.pos; } void cdq(int l,int r){ if(l>=r) return; int mid=((l+r)>>1); cdq(l,mid); std::sort(a+l,a+mid+1); std::sort(a+mid+1,a+r+1); int lptr=l; rin(rptr,mid+1,r){ while(lptr<=mid&&a[lptr].x<a[rptr].x){ Add(a[lptr].y,a[lptr].f); lptr++; } a[rptr].f=std::max(a[rptr].f,Ask(a[rptr].y-1)+1); } rin(i,l,lptr-1) Add(a[i].y,-1); rin(i,mid+1,r) c[i]=a[i]; rin(i,mid+1,r) a[c[i].pos]=c[i]; // std::sort(a+mid+1,a+r+1,cmp); cdq(mid+1,r); } int main(){ n=read(); rin(i,1,n){ a[i].x=read(); b[i]=a[i].y=read(); a[i].pos=i; } std::sort(b+1,b+n+1); siz=std::unique(b+1,b+n+1)-b-1; rin(i,1,n) a[i].y=std::lower_bound(b+1,b+n+1,a[i].y)-b; cdq(1,n); int ans=1; rin(i,1,n) ans=std::max(ans,a[i].f); printf("%d\n",ans); return 0; }