【题目大意】
首先输入N个整数,接下来N行每行输入两个整数x,y表示i号点的x,y坐标
输出所有满足i<j且xi<xj,yi<yj的最长上升序列。
【解题思路】
第一眼看起来像是二维偏序的问题,但是注意到本题其实是在空间里面的一条最长上升折线,所以还需要考虑下标的问题。
所以本题转化为了一个三维偏序问题,指满足i<j且id_i<id_j,xi<xj,yi<yj的最长上升序列。
三维偏序问题,可以使用CDQ学姐发明的算法,用以下一句话概括:
一维排序,二维分治,三维树状数组。
其算法框架是:
首先分治处理左半边序列。
然后想归并排序处理逆序对一样将左右两半区间排序,指针扫过去,然后利用树状数组统计答案。
这么做的正确性在于右半边的答案来源于左半边的答案处理好之后,利用DP进行更新。
最后递归处理右半部分。
答案是所有点的答案的最大值。
注意本题需要离散
【代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cctype>
#include<iomanip>
#define LL long long
//#define LOCAL
#define lowbit(x) (x&(-x))
using namespace std;
const int N=100111;
int n;
int a[N];
int ans=1;
struct Seq{
int x,y,ans,id;
}q[N];
bool Cmpa(const Seq &A,const Seq &B){
return A.x<B.x;
}
bool Cmpb(const Seq &A,const Seq &B){
return A.id<B.id;
}
struct BIT{
int tree[N<<2];
void Add(int pos,int val){
while (pos<=N){
tree[pos]=max(tree[pos],val);
pos+=lowbit(pos);
}
}
void Clear(int pos){
while (pos<=N){
tree[pos]=0;
pos+=lowbit(pos);
}
}
int Query(int pos){
int ret=0;
while (pos){
ret=max(ret,tree[pos]);
pos-=lowbit(pos);
}
return ret;
}
}bit;
void CDQ(int l,int r){
if (l==r) return;
int mid=(l+r)>>1;
CDQ(l,mid);
sort(q+l,q+mid+1,Cmpa);
sort(q+mid+1,q+r+1,Cmpa);
int posl=l,posr=mid+1;
while (posr<=r){
while (posl<=mid&&q[posl].x<q[posr].x){
bit.Add(q[posl].y,q[posl].ans);
posl++;
}
q[posr].ans=max(q[posr].ans,bit.Query(q[posr].y-1)+1);
posr++;
}
for (int i=l;i<=mid;++i) bit.Clear(q[i].y);
sort(q+mid+1,q+r+1,Cmpb);
CDQ(mid+1,r);
}
int nn;
inline void Discret(){
sort(a+1,a+n+1);
nn=unique(a+1,a+n+1)-a-1;
}
int Push_In(int x){
return lower_bound(a+1,a+nn+1,x)-a;
}
int main(){
#ifdef LOCAL
freopen("SPOJ-LIS2.in","r",stdin);
#endif
scanf("%d",&n);
for (int i=1;i<=n;++i){
q[i].ans=1;
q[i].id=i;
scanf("%d%d",&q[i].x,&q[i].y);
a[i]=q[i].y;
}
Discret();
for (int i=1;i<=n;++i) q[i].y=Push_In(q[i].y);
CDQ(1,n);
for (int i=1;i<=n;++i) ans=max(ans,q[i].ans);
printf("%d\n",ans);
return 0;
}
【总结】
三维偏序问题,利用CDQ算法优越的复杂度可以处理。
如果尚有高维偏序问题,则可以考虑多层CDQ套用。