AtCoder Beginner Contest 369
A - 369
思路
可能的位置只有左中右,如果\(A=B\)那么只有中间存在,如果\(A+B\)为奇数,那么只有中间不存在,反之均为3种;
AC代码
#include<bits/stdc++.h>
#define endl '\n'
#define int int long long
#define pb push_back
#define bs bitset
using namespace std;
typedef pair<char,int> PCI;
typedef pair<int,int> PII;
typedef priority_queue<int> PQ;
const int N = 2e5+10, MAX = 1e9, INF = -1e9;
int a,b;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>a>>b;
if(a==b)cout<<1<<endl;
else if((a+b)%2!=0)cout<<2<<endl;
else cout<<3<<endl;
return 0;
}
B - Piano 3
思路
根据题意模拟即可;
AC代码
#include<bits/stdc++.h>
#define endl '\n'
#define int int long long
#define pb push_back
#define bs bitset
using namespace std;
typedef pair<char,int> PCI;
typedef pair<int,int> PII;
typedef priority_queue<int> PQ;
const int N = 2e5+10, MAX = 1e9, INF = -1e9;
int n;
int e;
string s;
int ans=0;
int lp=0;
int rp=0;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>e>>s;
if(s=="L"){
if(lp!=0){
ans+=abs(lp-e);
}
lp=e;
}
else{
if(rp!=0){
ans+=abs(rp-e);
}
rp=e;
}
}
cout<<ans<<endl;
return 0;
}
C - Count Arithmetic Subarrays
思路
直接计算时间过不去,经过观察不难发现,对于一个算数级数序列来说,他的任意子序列均为算数序列,即若长度为&n&的序列包含的总共的个数为:\(C_n^2\),考虑到其他单独的数据,我们先计算出长度为1和2的个数,即\(2n-1\),后面统计所有的长度不小于3的算数序列长度即可,对于所有长度为\(i\)的序列答案还要加上\(C_i^2-(i-1)\),因此,假设长度大于等于3的算数序列个数为\(sum\),则最后的答案为:\(2n-1+\sum_{1}^{num}{C_i^2-(i-1)}\);
AC代码
#include<bits/stdc++.h>
#define endl '\n'
#define int int long long
#define pb push_back
#define bs bitset
using namespace std;
typedef pair<char,int> PCI;
typedef pair<int,int> PII;
typedef priority_queue<int> PQ;
const int N = 2e5+10, MAX = 1e9, INF = -1e9;
int n;
int a[N];
vector<int> v;
int ans=0;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
a[n+1]=a[n+2]=INF;
int num=0;
int e=2;
ans=n+n-1;
for(int i=2;i<=n;i++){
if(a[i+1]+a[i-1]==2*a[i])e++;
else{
if(e>=3)
v.pb(e);e=2;
}
}
for(auto i:v){
ans+=i*(i-1)/2;
ans-=i-1;
}
cout<<ans<<endl;
return 0;
}
D - Bonus EXP
思路
看数据大的大小就知道暴力枚举肯定是过不去的,由于我们发现结果具有可退推性,考虑动态规划,仿照01背包的思路,假设\(dp[i][j]\)表示在前\(i\)个怪物里面,击败\(j\)个怪物的经验最大值,显然\(i\) \(\geq\) \(j\),那么根据\(j\)的奇偶就可以得到转移方程:
\[dp[i][j] =
\begin{cases}
\max(dp[i-1][j],dp[i-1][j-1]+2a[i]) & j为偶数 \\
\\
max(dp[i-1][j],dp[i-1][j-1]+a[i]) & j为奇数\\
\end{cases}
\]
时间复杂度和空间复杂度均为\(O(n^2)\),还是不能满足题目要求,即使使用滚动数组降低空间复杂度至\(O(n)\)也不够,时间还是过不去;再观察不难发现,我们使用的并不是\(j\)本身,只需要它的奇偶性,那就可以只创建一个\(dp[N][2]\)的数组,用0代表奇数,1代表偶数,这样的就可以将转移方程简化:
\[dp[i][j] =
\begin{cases}
\max(dp[i-1][0],dp[i-1][1]+2a[i]) & j=0 \\
\\
max(dp[i-1][1],dp[i-1][0]+a[i]) & j=1\\
\end{cases}
\]
好了!现在我们将时间和空间复杂度都降低到了\(O(n)\),就满足了题目的要求,随后的答案就是在前\(n\)个怪物种,击败技术或者偶数个的较大者,即:\(max(dp[n][0],dp[n][1])\);
AC代码
#include<bits/stdc++.h>
#define endl '\n'
#define int int long long
#define pb push_back
#define bs bitset
using namespace std;
typedef pair<char,int> PCI;
typedef pair<int,int> PII;
typedef priority_queue<int> PQ;
const int N = 2e5 + 10, MAX = 1e9, INF = -1e9;
int n;
int a[N];
int dp[N][2];
int ans=-1;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
dp[1][1]=a[1];
dp[1][0]=0;
for(int i=2;i<=n;i++){
dp[i][0]=max(dp[i-1][1]+2*a[i],dp[i-1][0]);
dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
}
cout<<max(dp[n][0],dp[n][1])<<endl;
return 0;
}

浙公网安备 33010602011771号