abc134E - Sequence Decomposing
題意:給定一個序列,將其劃分成若干個不相交的嚴格上升子序列,求劃分的最小的子序列數量。
題解:
我們可以定義嚴格偏序關係,\(i \prec j\)當\(i< j\)且\(a_i< a_j\),也就是我們要將整個序列劃分成若干個鏈。
根據 Dilworth’s theorem,最小鏈覆蓋數=最大反鏈大小,
假設對於兩個在反鏈中的元素i,j不妨假設\(i<j\)
顯然有\(a_i \geq a_j\),也就是說最大反鏈大小等於最長不上升子序列的長度。
#include<bits/stdc++.h>
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define lc (o<<1)
#define rc ((o<<1)|1)
#define mk(x,y) make_pair((x),(y))
#define eb emplace_back
#define A puts("Yes")
#define B puts("No")
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const ll inf=1ll<<60;
const int N=2e5+5;
int a[N],n,b[N],m,c[N];
int lowbit(int x){
return x&(-x);
}
void upd(int x,int y){
for (;x<N;x+=lowbit(x)) c[x]=max(c[x], y);
}
int ask(int x){
int s=0;
for (;x;x-=lowbit(x)) s=max(s, c[x]);
return s;
}
int main(){
// freopen("data.in","r",stdin);
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-(b+1);
fo(i,1,n) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
int ans=0,x;
fd(i,n,1) {
x=ask(a[i])+1;
upd(a[i],x);
ans=max(ans, x);
}
printf("%d\n",ans);
return 0;
}