https://www.luogu.org/problemnew/show/P1020
第一问就是最长不上升子序列,第二问题解说用离散数学里的Dilworth定理,看不懂证明,它的结论是:将序列划分若干个为不上升子序列,使得划分的个数最小,那么这个个数等于序列的最长上升子序列的大小。
#include<bits/stdc++.h>
using namespace std;
int n;
int d[100005];
int L=1,R=0;
int d2[100005];
int binary(int v)
{
int l=L,r=R,m;
while(l<r)
{
m=(l+r)/2;
if(d[m]>=v)l=m+1;
else r=m;
}
return r;
}
int main()
{
// freopen("input.in","r",stdin);
fill(d,d+100005,-(1<<30));
fill(d2,d2+100005,(1<<30));
while(cin>>n)
{
R++;
int pos=binary(n);
d[pos]=n;
*lower_bound(d2+1,d2+R+1,n)=n;
}
for(int i=R;i>=L;i--)if(d[i]!=-(1<<30))
{
cout<<i<<endl;
break;
}
for(int i=R;i>=L;i--)if(d2[i]!=(1<<30))
{
cout<<i<<endl;
break;
}
return 0;
}
木棍加工 https://www.luogu.org/problemnew/show/P1233
这道题不能直接做,因为木棍的顺序可以打乱。
因此以长度为第一关键字,宽度为第二关键字,降序排列。然后就不用考虑长度了,只考虑宽度,可以用那个定理,最少的不上升子序列的划分数等于最长上升子序列的长度。
忘了o(nlogn)了,写了o(n^2)的
#include<bits/stdc++.h>
using namespace std;
int n,l[5005],w[5005],d[5005],idx[5005];
bool cmp(int i,int j)
{
if(l[i]!=l[j])return l[i]>l[j];
return w[i]>w[j];
}
int main()
{
// freopen("input.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)cin>>l[i]>>w[i];
for(int i=1;i<=n;i++)idx[i]=i;
sort(idx+1,idx+1+n,cmp);
for(int i=n;i>0;i--)
{
int maxn=0;
for(int j=i+1;j<=n;j++)if(w[idx[j]]>w[idx[i]])maxn=max(maxn,d[idx[j]]);
d[idx[i]]=maxn+1;
}
int maxn=0;for(int i=1;i<=n;i++)maxn=max(maxn,d[i]);
cout<<maxn<<endl;
return 0;
}