1、P1028魔族密码 :https://vijos.org/p/1028
分析:最长不下降子序列的变形, 把数字类比成前缀问题
#include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int maxn=2005; string word[maxn]; int a[maxn],s[maxn]; bool cmp(int i,int j) //比较是否为前缀 { int len=word[j].size(); for (int k=0;k<len;k++) if (word[j][k] != word[i][k]) return false; return true; } int main() { int n; scanf("%d",&n); for (int i=0;i<n;i++) { cin>>word[i]; s[i]=word[i].size(); } a[0]=1; for (int i=1;i<n;i++) //LIS模板 { for (int j=0;j<i;j++) { if (cmp(i,j)) a[i]=max(a[i],a[j]); } a[i]++; } int ans=0; for (int i=0;i<n;i++) ans=max(a[i],ans); printf("%d",ans); return 0; }
#include <cstdio> #include <iostream> using namespace std; const int maxn=1005; int main() { int f1[maxn],f2[maxn],a[maxn]; int n; scanf("%d",&n); for (int i=0;i<n;i++) scanf("%d",&a[i]); for (int i=0;i<n;i++) { f1[i]=1; f2[i]=1; } for (int i=1;i<n;i++) for (int j=0;j<i;j++) if (a[i]>a[j]) f1[i]=max(f1[i],f1[j]+1); for (int i=n-2;i>=0;i--) for (int j=n-1;j>i;j--) if (a[i]>a[j]) f2[i]=max(f2[i],f2[j]+1); int sum=0; for (int i=0;i<n;i++) sum=max(sum,f2[i]+f1[i]-1); //每个数被重复计数一次,应-1 sum=n-sum; printf("%d",sum); return 0; }
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=300005; struct Node { long long num; }; Node dp[maxn]; int main() { int n,k,len=0; long long tmp; scanf("%d%d",&n,&k); dp[0].num=-1; int top=0; for (int i=1;i<=k;i++) { scanf("%lld",&tmp); if (tmp > dp[top].num) { dp[++top].num=tmp; if (i == k) { len=top; } } else { int l=1,r=top; int mid; while (l <= r) { mid=(l+r)/2; if (tmp > dp[mid].num){ l=mid+1; } else{ r=mid-1; } } dp[l].num=tmp; if (i == k) len=l; } } top=1; dp[top].num=tmp; for (int i=k+1;i<=n;i++) { scanf("%lld",&tmp); if (tmp>dp[top].num){ dp[++top].num=tmp; } else { int l=1,r=top; int mid; while (l <= r) { mid=(l+r)/2; if (tmp > dp[mid].num){ l=mid+1; } else{ r=mid-1; } } if (l!=1) { dp[l].num=tmp; } } } printf("%d\n",top+len-1); return 0; }
//v=(|x1-x2|+|y1-y2|)^2 #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <iostream> using namespace std; struct node { int x,y,score; }; int poww(node a,node b) { return (abs(a.x-b.x)+abs(a.y-b.y))*(abs(a.x-b.x)+abs(a.y-b.y)); } node sum[2501]; int main() { int n,a; scanf("%d",&n); for (int i=0;i<n;i++) for (int j=0;j<n;j++){ scanf("%d",&a); sum[a].x=i; sum[a].y=j; } for (int i=n*n-1;i>=1;i--) // 逆序LIS for (int j=i+1;j<=n*n;j++) { int p=poww(sum[i],sum[j]); sum[i].score=max(sum[j].score+p,sum[i].score); } printf("%d\n",sum[1].score); return 0; }
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=10005; int a[maxn],f[maxn]; int main() { int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) { if (f[i]%2==1){ //奇数情况 if (a[j]>a[i]) f[j]=max(f[j],f[i]+1); } else if(f[i]%2==0) //偶数情况 if (a[j]<a[i]) f[j]=max(f[j],f[i]+1); } int ans=0; for (int i=1;i<=n;i++) ans=max(ans,f[i]); cout<<ans+1<<endl; return 0; }
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=505; //// dp[i][j] 表示 第一串前i个, 第二串前j个 并且以b[j]结尾 的最大公共子序列 int a[maxn],b[maxn]; int dp[maxn][maxn]; int main() { int t; scanf("%d",&t); while (t--) { int n,m; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); scanf("%d",&m); for (int i=0;i<m;i++) scanf("%d",&b[i]); memset(dp,0,sizeof(dp)); for (int i=0;i<n;i++) { int _max=0; for (int j=0;j<m;j++) { dp[i+1][j+1]=dp[i][j+1]; if (a[i] > b[j]) { _max=max(_max,dp[i][j+1]); } if (a[i] == b[j]) dp[i+1][j+1]=_max+1; } } int ans=0; for (int i=1;i<=m;i++) ans=max(ans,dp[n][i]); printf("%d\n",ans); } return 0; }