洛谷 P1233 木棍加工 题解
Dilworth定理:在数学理论中的序理论与组合数学中,Dilworth定理根据序列划分的最小数量的链描述了任何有限偏序集的宽度。
反链是一种偏序集,其任意两个元素不可比;而链则是一种任意两个元素可比的偏序集。Dilworth定理说明,存在一个反链A与一个将序列划分为链族P的划分,使得划分中链的数量等于集合A的基数。当存在这种情况时,对任何至多能包含来自P中每一个成员一个元素的反链,A一定是此序列中的最大反链。同样地,对于任何最少包含A中的每一个元素的一个链的划分,P也一定是序列可以划分出的最小链族。偏序集的宽度被定义为A与P的共同大小。
另一种Dilworth定理的等价表述是:在有穷偏序集中,任何反链最大元素数目等于任何将集合到链的划分中链的最小数目。一个关于无限偏序集的理论指出,在此种情况下,一个偏序集具有有限的宽度w,当且仅当它可以划分为最少w条链。
对于dilworth定理,我的理解就是:
在一个序列中 最长下降子序列的个数(下降子序列的最小划分)就等于其最长不下降子序列的长度
#include <bits/stdc++.h> #pragma GCC optimize(2) using namespace std; struct haha{ int a; int b; }lala[2000010]; int n; inline bool cmp(haha x,haha y) { if(x.a==y.a) return x.b>y.b; return x.a>y.a; } int c[2000010]; inline int lowbit(register int x) { return x&(-x); } int maxn; inline int ask(register int x) { register int res=0; while(x>0){ if(res<c[x]){ res=c[x]; } x-=lowbit(x); } return res; } inline void add(register int x,register int v) { while(x<=maxn){ c[x]=max(c[x],v); x+=lowbit(x); } } int main() { cin>>n; for(register int i=1;i<=n;i++){ scanf("%d%d",&lala[i].a,&lala[i].b); maxn=max(maxn,lala[i].b); } sort(lala+1,lala+1+n,cmp); register int ans=0; for(register int i=1;i<=n;i++){ register int j=ask(lala[i].b)+1; ans=max(ans,j); add(lala[i].b+1,j); } cout<<ans; }
众人皆醉我独醒,举世皆浊我独清