一.CF1389B Array Walk
题意
思路
可以枚举向右走1~k步的情况,每向右走一步,可以选择向左来回走0~z次,然后取总分的最大值,由于z不大于5,因此复杂度为
O
(
n
)
O(n)
O(n)
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#define ll long long
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+10;
const double esp=1e-5;
const ll mod=1e9+7;
int t,n,k,z,a[N],sum[N];
int main()
{
cin>>t;
while(t--){
cin>>n>>k>>z;
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
int ans=0,tmp;
for(int i=1;i<=n&&k>0;i++,k--){
tmp=sum[i];
for(int j=0;j<=z&&2*j<=k;j++){
int r=k-2*j;//来回走j次之后还剩余的步数
tmp=max(tmp,(a[i]+a[i+1])*j+sum[i+r]);
}
ans=max(tmp,ans);
}
cout<<ans<<endl;
}
return 0;
}
二.CF255C Almost Arithmetical Progression
题意
先给出一个整数
n
n
n ,再给出一个有
n
n
n 个元素的序列
b
b
b。
现在要你求序列
b
b
b 中最长的子序列,满足隔位的两个数相等,问这个最长的子序列的长度是多少。
思路
在这个题中,
b
b
b数组的范围很大,所以应该要离散化.
然后,设
f
i
,
a
j
f_{i,a_j}
fi,aj表示在前
i
i
i个数中,另一个数是
a
j
a_{j}
aj(离散化后)时满足条件的最大子序列长度,所以
f
i
,
a
j
f_{i,a_j}
fi,aj应满足:
f
i
,
a
j
=
m
a
x
(
f
i
,
a
j
,
f
j
,
a
i
+
1
)
f_{i,a_j}=max(f_{i,a_j},f_{j,a_i}+1)
fi,aj=max(fi,aj,fj,ai+1)
时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#include<bitset>
#define ll long long
using namespace std;
const int N=1e6+10;
const double esp=1e-5;
const ll mod=1e9+7;
//f[i][a[j]]:表示在前i个数中,另一个数是a[j]时符合条件的最大长度
int n,a[N],f[4005][4005],cnt;
int ans;
map<int,int> mp;
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(!mp[a[i]])//用map离散化
mp[a[i]]=++cnt;
}
if(n<2)
ans=n;
else{
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
ans=max(ans,f[i][mp[a[j]]]=max(f[i][mp[a[j]]],f[j][mp[a[i]]]+1));
}
}
ans++;
}
cout<<ans<<endl;
return 0;
}
/*
11
12 8 12 8 6 8 6 12 8 8 6
8
2 2 2 3 2 3 2 4
3
2 2 2
5
3 3 2 3 3
*/
三.AcWing4378. 选取数对
题意
思路
可以设
f
[
i
]
[
j
]
=
f[i][j]=
f[i][j]=为以
a
[
i
]
a[i]
a[i]结尾,选取
j
j
j个区间时的总和最大值.
先用一个s数组保存前缀和,然后枚举1~k个区间,在1~k中,枚举j*m到n来求每一个
f
[
i
]
[
j
]
f[i][j]
f[i][j],最后取
f
[
i
]
[
k
]
f[i][k]
f[i][k]的最大值即可
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> pii;
const int N=5005;
const double esp=1e-5;
const ll mod=1e9+7;
int n,m,k;
//f[i][j]:以a[i]结尾,选取j个区间时的总和最大值
ll a[N],f[N][N],s[N];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
s[i]+=a[i]+s[i-1];
}
for(int i=1;i<=k;i++){
ll maxf=0;
for(int j=i*m;j<=n;j++){
maxf=max(maxf,f[j-m][i-1]+s[j]-s[j-m]);
f[j][i]=maxf;
}
}
ll ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,f[i][k]);
printf("%lld\n",ans);
return 0;
}
/*
5 2 1
1 2 3 4 5
*/
四. NC234864 造桥
思路
定义dp数组:dp[i][j]为在前i个字符串中,以j字符结尾的最大字符串长度,则状态方程为
d
p
[
i
]
[
t
a
i
l
]
=
m
a
x
(
d
p
[
i
−
1
]
[
t
a
i
l
]
,
d
p
[
i
−
1
]
[
h
e
a
d
]
+
l
e
n
)
dp[i][tail]=max(dp[i-1][tail],dp[i-1][head]+len)
dp[i][tail]=max(dp[i−1][tail],dp[i−1][head]+len)
其中tail为第i个字符串的最后一个字符,head为第i个字符串的第一个字符.
代码
#include<iostream>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#define ll long long
#define SE_IT set<node>::iterator
#define inf 0x3f3f3f3f
#define bug(a) cout<<"* "<<a<<endl;
#define bugg(a,b) cout<<"** "<<a<<" "<<b<<endl;
#define buggg(a,b,c) cout<<"*** "<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+10;
const double esp=1e-5;
const ll mod=1e9+7;
//dp[i][j]:在前i个字符串中,以j字符结尾的最大字符串长度
int t,n,dp[N][30];
string s[N];
int main()
{
cin>>t;
while(t--){
cin>>n;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
cin>>s[i];
}
int ans=0;
for(int i=1;i<=n;i++){
int len=s[i].size();
int head=s[i][0]-'a',tail=s[i][len-1]-'a';
for(int j=0;j<26;j++){
if(j==tail){
dp[i][tail]=max(dp[i-1][tail],dp[i-1][head]+len);
// bug(dp[i][tail])
}
else
dp[i][j]=dp[i-1][j];
}
// bug(dp[i][tail])
ans=max(ans,dp[i][tail]);
}
cout<<ans<<endl;
}
return 0;
}
五.CF788A Functions again
题意
思路
此题为dp求最大连续子序列和,根据题意,子序和有两种情况,所以应该求两次取最大的一次即可
代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
#include<unordered_map>
#include<stack>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<string>
#include<map>
#define ll long long
#define endl "\n"
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+10;
const double esp=1e-5;
const ll mod=1e9+7;
int t,n;
ll a[N],ans=-inf;
//dp[i]:到当前为止,以a[i]为最后一个数的最大子序和
ll dp[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<n;i++)
a[i]=abs(a[i+1]-a[i]);
for(int i=1;i<n;i++){
if(i&1){
dp[i]=max(dp[i-1]+a[i],a[i]);
}
else
dp[i]=max(dp[i-1]-a[i],-a[i]);
//bug(dp[i])
ans=max(dp[i],ans);
}
memset(dp,0,sizeof(dp));
for(int i=2;i<n;i++){
if(i&1){
dp[i]=max(dp[i-1]-a[i],-a[i]);
}
else
dp[i]=max(dp[i-1]+a[i],a[i]);
//bug(dp[i])
ans=max(dp[i],ans);
}
cout<<ans<<endl;
return 0;
}