abc134E - Sequence Decomposing

gan_coder發表於2024-07-13

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;
}

相關文章