题单链接
#include
#include
using namespace std;
int arr[100010],n,dp[100010],lds,cnt,f[100010],lis;
int ldsfind(int x){
int ans=0;
for(int i=1;i<x;i++){
if(arr[i]>=arr[x]&&dp[i]>ans) ans=dp[i];
}
return ans;
}
int lisfind(int x){
int ans=0;
for(int i=1;i<x;i++){
if(arr[i]<arr[x]&&f[i]>ans) ans=f[i];
}
return ans;
}
int main(){
while(cin>>arr[++n]);n--;
dp[1]=1;f[1]=1;
for(int i=2;i<=n;i++){
dp[i]=ldsfind(i)+1;
f[i]=lisfind(i)+1;
}
for(int i=1;i<=n;i++){
lds=max(lds,dp[i]);
lis=max(lis,f[i]);
}
cout<<lds<<endl;
cout<<lis<<endl;
}
#include
#include
using namespace std;
int arr[100010],len=1,x[100010],n;
int find(int i){
int l=1,r=len,ans=-1;
while(l<=r){
int mid=(l+r)>>1;
if(arr[i]>x[mid]){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int find2(int i){
int l=1,r=len,ans=-1;
while(l<=r){
int mid=(l+r)>>1;
if(arr[i]<=x[mid]){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int main(){
while(cin>>arr[++n]);n--;
x[1]=arr[1];
for(int i=2;i<=n;i++){
if(arr[i]<=x[len]) x[++len]=arr[i];
else{
x[find(i)]=arr[i];
}
}
cout<<len<<endl;
len=1;
x[1]=arr[1];
for(int i=2;i<=n;i++){
if(arr[i]>x[len]) x[++len]=arr[i];
else{
x[find2(i)]=arr[i];
}
}
cout<<len<<endl;
}
参考博客
#include
#include
using namespace std;
int n,a[10010],b[10010],f[10010][10010];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
f[1][0]=f[0][1]=f[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1;
else{
f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
}
cout<<f[n][n]<<endl;
}
#include
#include
using namespace std;
int a[100010],b[100010],mp[100010],len=1,x[100010],n;
int find(int i){
int l=1,r=len,ans=-1;
while(l<=r){
int mid=(l+r)>>1;
if(mp[b[i]]<=x[mid]){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];mp[a[i]]=i;
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
x[1]=mp[b[1]];
for(int i=2;i<=n;i++){
if(mp[b[i]]>x[len]) x[++len]=mp[b[i]];
else{
x[find(i)]=mp[b[i]];
}
}
cout<<len<<endl;
}
#include
#include
int n,k;
using namespace std;
const int maxn=10010;
struct node{
int p,t;
bool operator<(const node& n) const{
return p>n.p;
}
}a[maxn];
int b[maxn],cnt=1,f[maxn];
int main(){
cin>>n>>k;
for(int i=1;i<=k;i++){
cin>>a[i].p>>a[i].t;
b[a[i].p]++;
}
sort(a+1,a+k+1);
for(int i=n;i>=1;i--){
if(b[i]==0) f[i]=f[i+1]+1;
else{
for(int j=1;j<=b[i];j++){
f[i]=max(f[i],f[i+a[cnt].t]);
cnt++;
}
}
}
cout<<f[1]<<endl;
}
#include
#include
#include
using namespace std;
string A,B;
int f[2010][2010];
int main(){
cin>>A>>B;A.insert(0," ");B.insert(0," ");
for(int i=0;i<A.length();i++) f[i][0]=i;
for(int j=0;j<B.length();j++) f[0][j]=j;
for(int i=1;i<A.length();i++){
for(int j=1;j<B.length();j++){
f[i][j]=min(f[i-1][j]+1,min(f[i][j-1]+1,f[i-1][j-1]+(A[i]==B[j]?0:1)));
}
}
cout<<f[A.length()-1][B.length()-1]<<endl;
}
#include
#include
typedef long long ll;
using namespace std;
int n,root[40][40];
ll f[40][40];
void preorder(ll l,ll r){
if(l<=r){
cout<<root[l][r]<<" ";
preorder(l,root[l][r]-1);
preorder(root[l][r]+1,r);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>f[i][i];
f[i][i-1]=1;//子树不存在,返回1
root[i][i]=i;
}
for(int len=1;len<=n;len++){
for(int l=1;l+len-1<=n;l++){
int r=l+len-1;
for(int k=l;k<r;k++){
if(f[l][r]<f[l][k-1]*f[k+1][r]+f[k][k]){
f[l][r]=f[l][k-1]*f[k+1][r]+f[k][k];
root[l][r]=k;
}
}
}
}
cout<<f[1][n]<<endl;
preorder(1,n);
}
#include
#include
#include
typedef long long ll;
using namespace std;
ll ans,mod=998244353,f[1010][40010];
int h[1010],tot,maxh=20010,n;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>h[i];
}
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
f[i][h[i]-h[j]+maxh]=(f[i][h[i]-h[j]+maxh]+f[j][h[i]-h[j]+maxh]+1)%mod;
ans=(ans+f[j][h[i]-h[j]+maxh]+1)%mod;
}
}
ans=(ans+n)%mod;
cout<<ans<<endl;
}
#include
#include
using namespace std;
int n,m,a[110],f[110][110],mod=1000007;
//f[i][j]用前i种花组成j盆的方案数
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=0;i<=n;i++){
f[i][0]=1;
}
for(int i=1;i<=n;i++){
for(int k=0;k<=a[i];k++){//第i种花选k盆
for(int j=0;j<=m-k;j++){
//从已装的j盆转移过来
if(k==0&&j==0) continue;
f[i][j+k]+=f[i-1][j];
f[i][j+k]%=mod;
}
}
}
cout<<f[n][m]<<endl;
}
狄尔沃斯(Dilworth)定理:对于任意有限偏序集,其最大反链中元素的数目必等于最小链划分中链的数目;其最长链中元素的数目必等于其最小反链划分中反链的数目
#include
#include
using namespace std;
int n,dp[5010],ans;
struct stick{
int l,w;
bool operator<(const stick& t)const{
return l>t.l;
}
}s[5010];
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>s[i].l>>s[i].w;
}
sort(s,s+n);
dp[0]=1;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(s[j].w<s[i].w){
dp[i]=max(dp[i],dp[j]);
}
}
dp[i]+=1;
}
for(int i=0;i<n;i++){
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
}
分别正向、反向求最长上升子序列即可。
#include
#include
using namespace std;
int n,t[110],f[110],g[110],ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>t[i];
}
//正向最长上升子序列
f[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
if(t[i]>t[j]){
f[i]=max(f[i],f[j]);
}
}
f[i]+=1;
}
//逆向最长上升子序列
g[n]=1;
for(int i=n-1;i>=1;i--){
for(int j=n;j>i;j--){
if(t[i]>t[j]){
g[i]=max(g[i],g[j]);
}
}
g[i]+=1;
}
for(int i=1;i<=n;i++){
ans=max(ans,f[i]+g[i]-1);
}
cout<<n-ans<<endl;
}
#include
#include
using namespace std;
int n,w,s;
long long dp[5510][5510],inf=1e18,ans=-inf,a[5510];
int main(){
cin>>n>>w>>s;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=0;i<=n;i++){
for(int j=0;j<=w;j++){
dp[i][j]=-inf;
}
}
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=w;j++){
for(int k=j-1;k<=min(w,j+s-1);k++){
dp[i][j]=max(dp[i][j],dp[i-1][k]+a[i]*j);
}
}
}
for(int j=1;j<=w;j++){
ans=max(ans,dp[n][j]);
}
cout<<ans<<endl;
}
#include
#include
#include
using namespace std;
int n,w,s;
long long dp[5510][5510],inf=1e18,ans=-inf,a[5510];
int main(){
cin>>n>>w>>s;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=0;i<=n;i++){
for(int j=0;j<=w;j++){
dp[i][j]=-inf;
}
}
dp[0][0]=0;
for(int i=1;i<=n;i++){
//单调递减队列
deque<int>q;q.push_back(0);
for(int j=min(w,i);j>=1;j--){
while(q.size()&&q.front()>j+s-1) q.pop_front();
while(q.size()&&dp[i-1][q.back()]<dp[i-1][j])q.pop_back();
q.push_back(j);
dp[i][j]=max(dp[i-1][q.front()],dp[i-1][j-1])+j*a[i];
}
}
for(int j=1;j<=w;j++){
ans=max(ans,dp[n][j]);
}
cout<<ans<<endl;
}