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;
	}

t.b.c.

posted @ 2024-09-30 20:48  Oaths  阅读(12)  评论(0)    收藏  举报