思维训练4

题目描述1

Problem - A - Codeforces

思维训练4_第1张图片

题目分析

对于此题我们要求差值种类最大,故我们可以构造出相邻差值分别为1,2,3...由于n规定了最大的范围故我们增到一定的差值之后其差值必定为之前出现过的数字,但由于要保证数组呈递增趋势故可以在(n + i - k) 与 (a[i - 1] + i - 1)中取到最小的那个以保证可以在范围内。

#include
using namespace std;
const int N = 2e5 + 10;
void solve()
{
	int k, n, d, a[N];
	cin >> k >> n;
	a[1] = 1;
	for(int i = 2; i <= k; i ++)
	{
		a[i] = min(n + i - k, a[i - 1] + i - 1);
	}
	for(int i = 1; i <= k; i ++)cout << a[i] << ' ';
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述2

Problem - B - Codeforces

思维训练4_第2张图片

题目分析

思维训练4_第3张图片

#include
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
ll n, a[N], prefix[2][N];
void solve()
{
	cin >> n;
	for(int i = 1; i <= n; i ++)
	{
		cin >> a[i];
	}
	ll ans = 0, cnt1 = 0;
	for(int i = 1; i <= n; i ++)
	{
		if(a[i])cnt1 ++;
		else ans += cnt1;//逆序对数量 
		if(a[i] == 0)prefix[0][i] = prefix[0][i - 1] + 1;
		else prefix[0][i] = prefix[0][i - 1];
		if(a[i] == 1)prefix[1][i] = prefix[1][i - 1] + 1;
		else prefix[1][i] = prefix[1][i - 1];
	}
	ll sum = ans;
	for(int i = 1; i <= n; i ++)
	{
		if(a[i])//将1改为0 
		{
			ll d = prefix[1][i - 1] - (prefix[0][n] - prefix[0][i]);//左1减右0
			ans = max(ans, sum + d); 
		}
		else
		{
			ll d = (prefix[0][n] - prefix[0][i]) - prefix[1][i - 1];//右0减左1 
			ans = max(ans, sum + d);
		}
	}
	cout << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述3

Problem - C - Codeforces

思维训练4_第4张图片

 题目分析

对于a和c的相对位置是不会发生变化的,其分别可以借助b向右移和左移。

本题确定三点:

1.a,c子序列相等

2.所有a仅右移

3.所有c仅左移

思维训练4_第5张图片

#include
using namespace std;
const int N = 2e5 + 10;
int n, flag;
char s[N], t[N];
void solve()
{
	flag = 0;
	string ss = "", tt = "";
	cin >> n;
	cin >> s + 1 >> t + 1; 
	for(int i = 1; i <= n; i ++)
	{
		if(s[i] != 'b')ss += s[i];
		if(t[i] != 'b')tt += t[i];
	}
	if(ss != tt)flag = 1;
	if(flag)
	{
		cout << "NO" << '\n';
		return;
	}
	vector sa, sc, ta, tc;
	for(int i = 1; i <= n; i ++)
	{
		if(s[i] == 'a')sa.push_back(i);
		if(s[i] == 'c')sc.push_back(i);
		if(t[i] == 'a')ta.push_back(i);
		if(t[i] == 'c')tc.push_back(i);
	}
	flag = 1;
	for(int i = 0; i < sa.size() && flag; i ++)
	{
		if(sa[i] > ta[i])flag = 0;	
	}
	for(int i = 0; i < sc.size() && flag; i ++)
	{
		if(sc[i] < tc[i])flag = 0;
	}
	if(!flag)cout << "NO" << '\n';
	else cout << "YES" << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述4

思维训练4_第6张图片

cnt[w] :  在w位的数的个数

思维训练4_第7张图片

#include
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int a[N], cnt[N];
int getpos(int x)
{
	int res = 0;
	while(x)res ++, x >>= 1;
	return res;
}
void solve()
{
	int n;
	 cin >> n;
	 memset(cnt, 0, sizeof cnt);
	 for(int i = 1; i <= n; i ++)
	 {
	 	cin >> a[i];
	 }
	 ll ans = 0;
	 for(int i = 1; i <= n; i ++)
	 {
	 	int pos = getpos(a[i]);
	 	ans += cnt[pos] ++;
	 }
	 cout << ans << '\n';
}
int main()
{
	int t;
	cin >> t;
	while(t --)
	{
		solve();	
	} 
	return 0;
}

 题目描述5

Problem - E - Codeforces

思维训练4_第8张图片

题目分析 

题意为将相加为t的两个数字尽量分在不同的组中,如果两个数相加为t的只能放在一组的时候,尽量将其平均放置

#include
using namespace std;
void solve()
{
	int n, t, x;
	cin >> n >> t;
	for(int i = 1, j = 0; i <= n; i ++)
	{
		cin >> x;
		if((1 + t) / 2 > x)cout << 1 << ' ';
		else if(t / 2 < x) cout << 0 << ' ';
		else cout << j << ' ', j ^= 1; 
	}
	cout << '\n';
}
int main()
{
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

你可能感兴趣的:(算法)